]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | #endif // !defined(BOOST_LOG_NO_THREADS) | |
112 | ||
113 | namespace aux { | |
114 | ||
115 | //! The metafunction selects the most strict lock type of the two | |
116 | template< | |
117 | typename LeftLockT, | |
118 | typename RightLockT, | |
119 | #if !defined(BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS) | |
120 | bool CondV = (thread_access_mode_of< LeftLockT >::value < thread_access_mode_of< RightLockT >::value) | |
121 | #else | |
122 | bool CondV = mpl::less< thread_access_mode_of< LeftLockT >, thread_access_mode_of< RightLockT > >::value | |
123 | #endif | |
124 | > | |
125 | struct strictest_lock_impl | |
126 | { | |
127 | typedef RightLockT type; | |
128 | }; | |
129 | template< typename LeftLockT, typename RightLockT > | |
130 | struct strictest_lock_impl< LeftLockT, RightLockT, false > | |
131 | { | |
132 | typedef LeftLockT type; | |
133 | }; | |
134 | ||
135 | } // namespace aux | |
136 | ||
137 | #if defined(BOOST_LOG_DOXYGEN_PASS) | |
138 | ||
139 | /*! | |
140 | * \brief The metafunction selects the most strict lock type of the specified. | |
141 | * | |
142 | * The template supports all lock types provided by the Boost.Thread | |
143 | * library (except for \c upgrade_to_unique_lock), plus additional | |
144 | * pseudo-lock \c no_lock that indicates no locking at all. | |
145 | * Exclusive locks are considered the strictest, shared locks are weaker, | |
146 | * and \c no_lock is the weakest. | |
147 | */ | |
148 | template< typename... LocksT > | |
149 | struct strictest_lock | |
150 | { | |
151 | typedef implementation_defined type; | |
152 | }; | |
153 | ||
154 | #else // defined(BOOST_LOG_DOXYGEN_PASS) | |
155 | ||
156 | #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
157 | ||
158 | template< typename LockT, typename... LocksT > | |
159 | struct strictest_lock; | |
160 | ||
161 | template< typename LockT > | |
162 | struct strictest_lock< LockT > | |
163 | { | |
164 | typedef LockT type; | |
165 | }; | |
166 | ||
167 | template< typename LeftLockT, typename RightLockT > | |
168 | struct strictest_lock< LeftLockT, RightLockT > | |
169 | { | |
170 | typedef typename aux::strictest_lock_impl< LeftLockT, RightLockT >::type type; | |
171 | }; | |
172 | ||
173 | template< typename LeftLockT, typename RightLockT, typename... LocksT > | |
174 | struct strictest_lock< LeftLockT, RightLockT, LocksT... > | |
175 | { | |
176 | typedef typename strictest_lock< | |
177 | typename aux::strictest_lock_impl< LeftLockT, RightLockT >::type, | |
178 | LocksT... | |
179 | >::type type; | |
180 | }; | |
181 | ||
182 | #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
183 | ||
184 | # define BOOST_LOG_TYPE_INTERNAL(z, i, data) BOOST_PP_CAT(T, BOOST_PP_INC(i)) | |
185 | ||
186 | template< | |
187 | typename T, | |
188 | BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PP_DEC(BOOST_LOG_STRICTEST_LOCK_LIMIT), typename T, void) | |
189 | > | |
190 | struct strictest_lock | |
191 | { | |
192 | typedef typename strictest_lock< | |
193 | typename boost::log::aux::strictest_lock_impl< T, T0 >::type | |
194 | BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_LOG_STRICTEST_LOCK_LIMIT, 2), BOOST_LOG_TYPE_INTERNAL, ~) | |
195 | >::type type; | |
196 | }; | |
197 | ||
198 | template< typename T > | |
199 | struct strictest_lock< | |
200 | T | |
201 | BOOST_PP_ENUM_TRAILING(BOOST_PP_DEC(BOOST_LOG_STRICTEST_LOCK_LIMIT), BOOST_LOG_PP_IDENTITY, void) | |
202 | > | |
203 | { | |
204 | typedef T type; | |
205 | }; | |
206 | ||
207 | # undef BOOST_LOG_TYPE_INTERNAL | |
208 | ||
209 | #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
210 | ||
211 | #endif // defined(BOOST_LOG_DOXYGEN_PASS) | |
212 | ||
213 | BOOST_LOG_CLOSE_NAMESPACE // namespace log | |
214 | ||
215 | } // namespace boost | |
216 | ||
217 | #include <boost/log/detail/footer.hpp> | |
218 | ||
219 | #endif // BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_ |