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