Chris@16: /* Chris@101: * Copyright Andrey Semashev 2007 - 2015. Chris@16: * Distributed under the Boost Software License, Version 1.0. Chris@16: * (See accompanying file LICENSE_1_0.txt or copy at Chris@16: * http://www.boost.org/LICENSE_1_0.txt) Chris@16: */ Chris@16: /*! Chris@16: * \file utility/strictest_lock.hpp Chris@16: * \author Andrey Semashev Chris@16: * \date 30.05.2010 Chris@16: * Chris@16: * The header contains definition of the \c strictest_lock metafunction that Chris@16: * allows to select a lock with the strictest access requirements. Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_ Chris@16: #define BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_ Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #endif Chris@16: #if defined(BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS) Chris@16: #include Chris@16: #endif Chris@16: #include Chris@16: Chris@16: #ifdef BOOST_HAS_PRAGMA_ONCE Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: #if !defined(BOOST_LOG_STRICTEST_LOCK_LIMIT) Chris@16: /*! Chris@16: * The macro defines the maximum number of template arguments that the \c strictest_lock Chris@16: * metafunction accepts. Should not be less than 2. Chris@16: */ Chris@16: #define BOOST_LOG_STRICTEST_LOCK_LIMIT 10 Chris@16: #endif // BOOST_LOG_STRICTEST_LOCK_LIMIT Chris@16: #if BOOST_LOG_STRICTEST_LOCK_LIMIT < 2 Chris@16: #error The BOOST_LOG_STRICTEST_LOCK_LIMIT macro should not be less than 2 Chris@16: #endif Chris@16: #endif // defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: BOOST_LOG_OPEN_NAMESPACE Chris@16: Chris@16: //! Access modes for different types of locks Chris@16: enum lock_access_mode Chris@16: { Chris@16: unlocked_access, //!< A thread that owns this kind of lock doesn't restrict other threads in any way Chris@16: shared_access, //!< A thread that owns this kind of lock requires that no other thread modify the locked data Chris@16: exclusive_access //!< A thread that owns this kind of lock requires that no other thread has access to the locked data Chris@16: }; Chris@16: Chris@16: //! The trait allows to select an access mode by the lock type Chris@16: template< typename LockT > Chris@16: struct thread_access_mode_of; Chris@16: Chris@16: template< typename MutexT > Chris@16: struct thread_access_mode_of< no_lock< MutexT > > : mpl::integral_c< lock_access_mode, unlocked_access > Chris@16: { Chris@16: }; Chris@16: Chris@16: #if !defined(BOOST_LOG_NO_THREADS) Chris@16: Chris@16: template< typename MutexT > Chris@16: struct thread_access_mode_of< lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access > Chris@16: { Chris@16: }; Chris@16: Chris@16: template< typename MutexT > Chris@16: struct thread_access_mode_of< unique_lock< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access > Chris@16: { Chris@16: }; Chris@16: Chris@16: template< typename MutexT > Chris@16: struct thread_access_mode_of< shared_lock< MutexT > > : mpl::integral_c< lock_access_mode, shared_access > Chris@16: { Chris@16: }; Chris@16: Chris@16: template< typename MutexT > Chris@16: struct thread_access_mode_of< upgrade_lock< MutexT > > : mpl::integral_c< lock_access_mode, shared_access > Chris@16: { Chris@16: }; Chris@16: Chris@16: template< typename MutexT > Chris@16: struct thread_access_mode_of< boost::log::aux::exclusive_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access > Chris@16: { Chris@16: }; Chris@16: Chris@16: template< typename MutexT > Chris@16: struct thread_access_mode_of< boost::log::aux::shared_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, shared_access > Chris@16: { Chris@16: }; Chris@16: Chris@16: #endif // !defined(BOOST_LOG_NO_THREADS) Chris@16: Chris@16: namespace aux { Chris@16: Chris@16: //! The metafunction selects the most strict lock type of the two Chris@16: template< Chris@16: typename LeftLockT, Chris@16: typename RightLockT, Chris@16: #if !defined(BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS) Chris@16: bool CondV = (thread_access_mode_of< LeftLockT >::value < thread_access_mode_of< RightLockT >::value) Chris@16: #else Chris@16: bool CondV = mpl::less< thread_access_mode_of< LeftLockT >, thread_access_mode_of< RightLockT > >::value Chris@16: #endif Chris@16: > Chris@16: struct strictest_lock_impl Chris@16: { Chris@16: typedef RightLockT type; Chris@16: }; Chris@16: template< typename LeftLockT, typename RightLockT > Chris@16: struct strictest_lock_impl< LeftLockT, RightLockT, false > Chris@16: { Chris@16: typedef LeftLockT type; Chris@16: }; Chris@16: Chris@16: } // namespace aux Chris@16: Chris@16: #if defined(BOOST_LOG_DOXYGEN_PASS) Chris@16: Chris@16: /*! Chris@16: * \brief The metafunction selects the most strict lock type of the specified. Chris@16: * Chris@16: * The template supports all lock types provided by the Boost.Thread Chris@16: * library (except for \c upgrade_to_unique_lock), plus additional Chris@16: * pseudo-lock \c no_lock that indicates no locking at all. Chris@16: * Exclusive locks are considered the strictest, shared locks are weaker, Chris@16: * and \c no_lock is the weakest. Chris@16: */ Chris@16: template< typename... LocksT > Chris@16: struct strictest_lock Chris@16: { Chris@16: typedef implementation_defined type; Chris@16: }; Chris@16: Chris@16: #else // defined(BOOST_LOG_DOXYGEN_PASS) Chris@16: Chris@16: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: template< typename LockT, typename... LocksT > Chris@16: struct strictest_lock; Chris@16: Chris@16: template< typename LockT > Chris@16: struct strictest_lock< LockT > Chris@16: { Chris@16: typedef LockT type; Chris@16: }; Chris@16: Chris@16: template< typename LeftLockT, typename RightLockT > Chris@16: struct strictest_lock< LeftLockT, RightLockT > Chris@16: { Chris@16: typedef typename aux::strictest_lock_impl< LeftLockT, RightLockT >::type type; Chris@16: }; Chris@16: Chris@16: template< typename LeftLockT, typename RightLockT, typename... LocksT > Chris@16: struct strictest_lock< LeftLockT, RightLockT, LocksT... > Chris@16: { Chris@16: typedef typename strictest_lock< Chris@16: typename aux::strictest_lock_impl< LeftLockT, RightLockT >::type, Chris@16: LocksT... Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: # define BOOST_LOG_TYPE_INTERNAL(z, i, data) BOOST_PP_CAT(T, BOOST_PP_INC(i)) Chris@16: Chris@16: template< Chris@16: typename T, Chris@16: BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PP_DEC(BOOST_LOG_STRICTEST_LOCK_LIMIT), typename T, void) Chris@16: > Chris@16: struct strictest_lock Chris@16: { Chris@16: typedef typename strictest_lock< Chris@16: typename boost::log::aux::strictest_lock_impl< T, T0 >::type Chris@16: BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_LOG_STRICTEST_LOCK_LIMIT, 2), BOOST_LOG_TYPE_INTERNAL, ~) Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template< typename T > Chris@16: struct strictest_lock< Chris@16: T Chris@16: BOOST_PP_ENUM_TRAILING(BOOST_PP_DEC(BOOST_LOG_STRICTEST_LOCK_LIMIT), BOOST_LOG_PP_IDENTITY, void) Chris@16: > Chris@16: { Chris@16: typedef T type; Chris@16: }; Chris@16: Chris@16: # undef BOOST_LOG_TYPE_INTERNAL Chris@16: Chris@16: #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: #endif // defined(BOOST_LOG_DOXYGEN_PASS) Chris@16: Chris@16: BOOST_LOG_CLOSE_NAMESPACE // namespace log Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_