Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:21

0001 /*
0002  *          Copyright Andrey Semashev 2007 - 2015.
0003  * Distributed under the Boost Software License, Version 1.0.
0004  *    (See accompanying file LICENSE_1_0.txt or copy at
0005  *          http://www.boost.org/LICENSE_1_0.txt)
0006  */
0007 /*!
0008  * \file   locks.hpp
0009  * \author Andrey Semashev
0010  * \date   30.05.2010
0011  *
0012  * \brief  This header is the Boost.Log library implementation, see the library documentation
0013  *         at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
0014  */
0015 
0016 #ifndef BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_
0017 #define BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_
0018 
0019 #include <boost/log/detail/config.hpp>
0020 #include <boost/log/detail/header.hpp>
0021 
0022 #ifdef BOOST_HAS_PRAGMA_ONCE
0023 #pragma once
0024 #endif
0025 
0026 namespace boost {
0027 
0028 #ifndef BOOST_LOG_NO_THREADS
0029 
0030 // Forward declaration of Boost.Thread locks. Specified here to avoid including Boost.Thread,
0031 // which would bring in many dependent headers, including a great deal of Boost.DateTime.
0032 template< typename >
0033 class lock_guard;
0034 template< typename >
0035 class shared_lock_guard;
0036 template< typename >
0037 class shared_lock;
0038 template< typename >
0039 class upgrade_lock;
0040 template< typename >
0041 class unique_lock;
0042 
0043 template< typename >
0044 struct is_mutex_type;
0045 
0046 #endif // BOOST_LOG_NO_THREADS
0047 
0048 BOOST_LOG_OPEN_NAMESPACE
0049 
0050 //! An auxiliary pseudo-lock to express no locking requirements in logger features
0051 template< typename MutexT >
0052 class no_lock
0053 {
0054 public:
0055     /*!
0056      * Constructs the pseudo-lock. The mutex is not affected during the construction.
0057      */
0058     explicit no_lock(MutexT&) BOOST_NOEXCEPT {}
0059 
0060 private:
0061     no_lock(no_lock const&);
0062     no_lock& operator= (no_lock const&);
0063 };
0064 
0065 namespace aux {
0066 
0067 #ifndef BOOST_LOG_NO_THREADS
0068 
0069 //! A trait to detect if the mutex supports exclusive locking
0070 template< typename MutexT >
0071 struct is_exclusively_lockable
0072 {
0073     typedef char true_type;
0074     struct false_type { char t[2]; };
0075 
0076     template< typename T >
0077     static true_type check_lockable(T*, void (T::*)() = &T::lock, void (T::*)() = &T::unlock);
0078     static false_type check_lockable(void*);
0079 
0080     enum value_t { value = sizeof(check_lockable((MutexT*)NULL)) == sizeof(true_type) };
0081 };
0082 
0083 //! A trait to detect if the mutex supports shared locking
0084 template< typename MutexT >
0085 struct is_shared_lockable
0086 {
0087     typedef char true_type;
0088     struct false_type { char t[2]; };
0089 
0090     template< typename T >
0091     static true_type check_shared_lockable(T*, void (T::*)() = &T::lock_shared, void (T::*)() = &T::unlock_shared);
0092     static false_type check_shared_lockable(void*);
0093 
0094     enum value_t { value = sizeof(check_shared_lockable((MutexT*)NULL)) == sizeof(true_type) };
0095 };
0096 
0097 //! A scope guard that automatically unlocks the mutex on destruction
0098 template< typename MutexT >
0099 struct exclusive_auto_unlocker
0100 {
0101     explicit exclusive_auto_unlocker(MutexT& m) BOOST_NOEXCEPT : m_Mutex(m)
0102     {
0103     }
0104     ~exclusive_auto_unlocker()
0105     {
0106         m_Mutex.unlock();
0107     }
0108 
0109     BOOST_DELETED_FUNCTION(exclusive_auto_unlocker(exclusive_auto_unlocker const&))
0110     BOOST_DELETED_FUNCTION(exclusive_auto_unlocker& operator= (exclusive_auto_unlocker const&))
0111 
0112 protected:
0113     MutexT& m_Mutex;
0114 };
0115 
0116 //! An analogue to the minimalistic \c lock_guard template. Defined here to avoid including Boost.Thread.
0117 template< typename MutexT >
0118 struct exclusive_lock_guard
0119 {
0120     explicit exclusive_lock_guard(MutexT& m) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m.lock())) : m_Mutex(m)
0121     {
0122         m.lock();
0123     }
0124     ~exclusive_lock_guard()
0125     {
0126         m_Mutex.unlock();
0127     }
0128 
0129     BOOST_DELETED_FUNCTION(exclusive_lock_guard(exclusive_lock_guard const&))
0130     BOOST_DELETED_FUNCTION(exclusive_lock_guard& operator= (exclusive_lock_guard const&))
0131 
0132 private:
0133     MutexT& m_Mutex;
0134 };
0135 
0136 //! An analogue to the minimalistic \c lock_guard template that locks \c shared_mutex with shared ownership.
0137 template< typename MutexT >
0138 struct shared_lock_guard
0139 {
0140     explicit shared_lock_guard(MutexT& m) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m.lock_shared())) : m_Mutex(m)
0141     {
0142         m.lock_shared();
0143     }
0144     ~shared_lock_guard()
0145     {
0146         m_Mutex.unlock_shared();
0147     }
0148 
0149     BOOST_DELETED_FUNCTION(shared_lock_guard(shared_lock_guard const&))
0150     BOOST_DELETED_FUNCTION(shared_lock_guard& operator= (shared_lock_guard const&))
0151 
0152 private:
0153     MutexT& m_Mutex;
0154 };
0155 
0156 //! A deadlock-safe lock type that exclusively locks two mutexes
0157 template< typename MutexT1, typename MutexT2 >
0158 class multiple_unique_lock2
0159 {
0160 public:
0161     multiple_unique_lock2(MutexT1& m1, MutexT2& m2) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.lock()) && BOOST_NOEXCEPT_EXPR(m2.lock())) :
0162         m_p1(&m1),
0163         m_p2(&m2)
0164     {
0165         // Yes, it's not conforming, but it works
0166         // and it doesn't require to #include <functional>
0167         if (static_cast< void* >(m_p1) < static_cast< void* >(m_p2))
0168         {
0169             m_p1->lock();
0170             m_p2->lock();
0171         }
0172         else
0173         {
0174             m_p2->lock();
0175             m_p1->lock();
0176         }
0177     }
0178     ~multiple_unique_lock2()
0179     {
0180         m_p2->unlock();
0181         m_p1->unlock();
0182     }
0183 
0184 private:
0185     MutexT1* m_p1;
0186     MutexT2* m_p2;
0187 };
0188 
0189 #endif // BOOST_LOG_NO_THREADS
0190 
0191 } // namespace aux
0192 
0193 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0194 
0195 } // namespace boost
0196 
0197 #include <boost/log/detail/footer.hpp>
0198 
0199 #endif // BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_