• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *          Copyright Andrey Semashev 2007 - 2015.
3  * Distributed under the Boost Software License, Version 1.0.
4  *    (See accompanying file LICENSE_1_0.txt or copy at
5  *          http://www.boost.org/LICENSE_1_0.txt)
6  */
7 /*!
8  * \file   utility/strictest_lock.hpp
9  * \author Andrey Semashev
10  * \date   30.05.2010
11  *
12  * The header contains definition of the \c strictest_lock metafunction that
13  * allows to select a lock with the strictest access requirements.
14  */
15 
16 #ifndef BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_
17 #define BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_
18 
19 #include <boost/mpl/integral_c.hpp>
20 #include <boost/log/detail/config.hpp>
21 #include <boost/log/detail/locks.hpp>
22 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
23 #include <boost/preprocessor/cat.hpp>
24 #include <boost/preprocessor/arithmetic/sub.hpp>
25 #include <boost/preprocessor/arithmetic/inc.hpp>
26 #include <boost/preprocessor/arithmetic/dec.hpp>
27 #include <boost/preprocessor/repetition/enum_trailing.hpp>
28 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
29 #include <boost/log/detail/pp_identity.hpp>
30 #endif
31 #if defined(BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS)
32 #include <boost/mpl/less.hpp>
33 #endif
34 #include <boost/log/detail/header.hpp>
35 
36 #ifdef BOOST_HAS_PRAGMA_ONCE
37 #pragma once
38 #endif
39 
40 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
41 #if !defined(BOOST_LOG_STRICTEST_LOCK_LIMIT)
42 /*!
43  * The macro defines the maximum number of template arguments that the \c strictest_lock
44  * metafunction accepts. Should not be less than 2.
45  */
46 #define BOOST_LOG_STRICTEST_LOCK_LIMIT 10
47 #endif // BOOST_LOG_STRICTEST_LOCK_LIMIT
48 #if BOOST_LOG_STRICTEST_LOCK_LIMIT < 2
49 #error The BOOST_LOG_STRICTEST_LOCK_LIMIT macro should not be less than 2
50 #endif
51 #endif // defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
52 
53 namespace boost {
54 
55 BOOST_LOG_OPEN_NAMESPACE
56 
57 //! Access modes for different types of locks
58 enum lock_access_mode
59 {
60     unlocked_access,    //!< A thread that owns this kind of lock doesn't restrict other threads in any way
61     shared_access,      //!< A thread that owns this kind of lock requires that no other thread modify the locked data
62     exclusive_access    //!< A thread that owns this kind of lock requires that no other thread has access to the locked data
63 };
64 
65 //! The trait allows to select an access mode by the lock type
66 template< typename LockT >
67 struct thread_access_mode_of;
68 
69 template< typename MutexT >
70 struct thread_access_mode_of< no_lock< MutexT > > : mpl::integral_c< lock_access_mode, unlocked_access >
71 {
72 };
73 
74 #if !defined(BOOST_LOG_NO_THREADS)
75 
76 template< typename MutexT >
77 struct thread_access_mode_of< lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access >
78 {
79 };
80 
81 template< typename MutexT >
82 struct thread_access_mode_of< shared_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, shared_access >
83 {
84 };
85 
86 template< typename MutexT >
87 struct thread_access_mode_of< unique_lock< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access >
88 {
89 };
90 
91 template< typename MutexT >
92 struct thread_access_mode_of< shared_lock< MutexT > > : mpl::integral_c< lock_access_mode, shared_access >
93 {
94 };
95 
96 template< typename MutexT >
97 struct thread_access_mode_of< upgrade_lock< MutexT > > : mpl::integral_c< lock_access_mode, shared_access >
98 {
99 };
100 
101 template< typename MutexT >
102 struct thread_access_mode_of< boost::log::aux::exclusive_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access >
103 {
104 };
105 
106 template< typename MutexT >
107 struct thread_access_mode_of< boost::log::aux::shared_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, shared_access >
108 {
109 };
110 
111 template< typename MutexT1, typename MutexT2 >
112 struct thread_access_mode_of< boost::log::aux::multiple_unique_lock2< MutexT1, MutexT2 > > : mpl::integral_c< lock_access_mode, exclusive_access >
113 {
114 };
115 
116 #endif // !defined(BOOST_LOG_NO_THREADS)
117 
118 namespace aux {
119 
120 //! The metafunction selects the most strict lock type of the two
121 template<
122     typename LeftLockT,
123     typename RightLockT,
124 #if !defined(BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS)
125     bool CondV = (thread_access_mode_of< LeftLockT >::value < thread_access_mode_of< RightLockT >::value)
126 #else
127     bool CondV = mpl::less< thread_access_mode_of< LeftLockT >, thread_access_mode_of< RightLockT > >::value
128 #endif
129 >
130 struct strictest_lock_impl
131 {
132     typedef RightLockT type;
133 };
134 template< typename LeftLockT, typename RightLockT >
135 struct strictest_lock_impl< LeftLockT, RightLockT, false >
136 {
137     typedef LeftLockT type;
138 };
139 
140 } // namespace aux
141 
142 #if defined(BOOST_LOG_DOXYGEN_PASS)
143 
144 /*!
145  * \brief The metafunction selects the most strict lock type of the specified.
146  *
147  * The template supports all lock types provided by the Boost.Thread
148  * library (except for \c upgrade_to_unique_lock), plus additional
149  * pseudo-lock \c no_lock that indicates no locking at all.
150  * Exclusive locks are considered the strictest, shared locks are weaker,
151  * and \c no_lock is the weakest.
152  */
153 template< typename... LocksT >
154 struct strictest_lock
155 {
156     typedef implementation_defined type;
157 };
158 
159 #else // defined(BOOST_LOG_DOXYGEN_PASS)
160 
161 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
162 
163 template< typename LockT, typename... LocksT >
164 struct strictest_lock;
165 
166 template< typename LockT >
167 struct strictest_lock< LockT >
168 {
169     typedef LockT type;
170 };
171 
172 template< typename LeftLockT, typename RightLockT >
173 struct strictest_lock< LeftLockT, RightLockT >
174 {
175     typedef typename aux::strictest_lock_impl< LeftLockT, RightLockT >::type type;
176 };
177 
178 template< typename LeftLockT, typename RightLockT, typename... LocksT >
179 struct strictest_lock< LeftLockT, RightLockT, LocksT... >
180 {
181     typedef typename strictest_lock<
182         typename aux::strictest_lock_impl< LeftLockT, RightLockT >::type,
183         LocksT...
184     >::type type;
185 };
186 
187 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
188 
189 #   define BOOST_LOG_TYPE_INTERNAL(z, i, data) BOOST_PP_CAT(T, BOOST_PP_INC(i))
190 
191 template<
192     typename T,
193     BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PP_DEC(BOOST_LOG_STRICTEST_LOCK_LIMIT), typename T, void)
194 >
195 struct strictest_lock
196 {
197     typedef typename strictest_lock<
198         typename boost::log::aux::strictest_lock_impl< T, T0 >::type
199         BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_LOG_STRICTEST_LOCK_LIMIT, 2), BOOST_LOG_TYPE_INTERNAL, ~)
200     >::type type;
201 };
202 
203 template< typename T >
204 struct strictest_lock<
205     T
206     BOOST_PP_ENUM_TRAILING(BOOST_PP_DEC(BOOST_LOG_STRICTEST_LOCK_LIMIT), BOOST_LOG_PP_IDENTITY, void)
207 >
208 {
209     typedef T type;
210 };
211 
212 #   undef BOOST_LOG_TYPE_INTERNAL
213 
214 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
215 
216 #endif // defined(BOOST_LOG_DOXYGEN_PASS)
217 
218 BOOST_LOG_CLOSE_NAMESPACE // namespace log
219 
220 } // namespace boost
221 
222 #include <boost/log/detail/footer.hpp>
223 
224 #endif // BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_
225