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 locks.hpp Chris@16: * \author Andrey Semashev Chris@16: * \date 30.05.2010 Chris@16: * Chris@16: * \brief This header is the Boost.Log library implementation, see the library documentation Chris@16: * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_ Chris@16: #define BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_ Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #ifdef BOOST_HAS_PRAGMA_ONCE Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: #ifndef BOOST_LOG_NO_THREADS Chris@16: Chris@16: // Forward declaration of Boost.Thread locks. Specified here to avoid including Boost.Thread, Chris@16: // which would bring in many dependent headers, including a great deal of Boost.DateTime. Chris@16: template< typename > Chris@16: class lock_guard; Chris@16: template< typename > Chris@16: class shared_lock; Chris@16: template< typename > Chris@16: class upgrade_lock; Chris@16: template< typename > Chris@16: class unique_lock; Chris@16: Chris@16: template< typename > Chris@16: struct is_mutex_type; Chris@16: Chris@16: #endif // BOOST_LOG_NO_THREADS Chris@16: Chris@16: BOOST_LOG_OPEN_NAMESPACE Chris@16: Chris@16: //! An auxiliary pseudo-lock to express no locking requirements in logger features Chris@16: template< typename MutexT > Chris@16: class no_lock Chris@16: { Chris@16: public: Chris@16: /*! Chris@16: * Constructs the pseudo-lock. The mutex is not affected during the construction. Chris@16: */ Chris@16: explicit no_lock(MutexT&) {} Chris@16: Chris@16: private: Chris@16: no_lock(no_lock const&); Chris@16: no_lock& operator= (no_lock const&); Chris@16: }; Chris@16: Chris@16: namespace aux { Chris@16: Chris@16: #ifndef BOOST_LOG_NO_THREADS Chris@16: Chris@16: //! A trait to detect if the mutex supports exclusive locking Chris@16: template< typename MutexT > Chris@16: struct is_exclusively_lockable Chris@16: { Chris@16: typedef char true_type; Chris@16: struct false_type { char t[2]; }; Chris@16: Chris@16: template< typename T > Chris@16: static true_type check_lockable(T*, void (T::*)() = &T::lock, void (T::*)() = &T::unlock); Chris@16: static false_type check_lockable(void*); Chris@16: Chris@16: enum value_t { value = sizeof(check_lockable((MutexT*)NULL)) == sizeof(true_type) }; Chris@16: }; Chris@16: Chris@16: //! A trait to detect if the mutex supports shared locking Chris@16: template< typename MutexT > Chris@16: struct is_shared_lockable Chris@16: { Chris@16: typedef char true_type; Chris@16: struct false_type { char t[2]; }; Chris@16: Chris@16: template< typename T > Chris@16: static true_type check_shared_lockable(T*, void (T::*)() = &T::lock_shared, void (T::*)() = &T::unlock_shared); Chris@16: static false_type check_shared_lockable(void*); Chris@16: Chris@16: enum value_t { value = sizeof(check_shared_lockable((MutexT*)NULL)) == sizeof(true_type) }; Chris@16: }; Chris@16: Chris@16: //! An analogue to the minimalistic \c lock_guard template. Defined here to avoid including Boost.Thread. Chris@16: template< typename MutexT > Chris@16: struct exclusive_lock_guard Chris@16: { Chris@16: explicit exclusive_lock_guard(MutexT& m) : m_Mutex(m) Chris@16: { Chris@16: m.lock(); Chris@16: } Chris@16: ~exclusive_lock_guard() Chris@16: { Chris@16: m_Mutex.unlock(); Chris@16: } Chris@16: Chris@16: private: Chris@16: exclusive_lock_guard(exclusive_lock_guard const&); Chris@16: exclusive_lock_guard& operator= (exclusive_lock_guard const&); Chris@16: Chris@16: private: Chris@16: MutexT& m_Mutex; Chris@16: }; Chris@16: Chris@16: //! An analogue to the minimalistic \c lock_guard template that locks \c shared_mutex with shared ownership. Chris@16: template< typename MutexT > Chris@16: struct shared_lock_guard Chris@16: { Chris@16: explicit shared_lock_guard(MutexT& m) : m_Mutex(m) Chris@16: { Chris@16: m.lock_shared(); Chris@16: } Chris@16: ~shared_lock_guard() Chris@16: { Chris@16: m_Mutex.unlock_shared(); Chris@16: } Chris@16: Chris@16: private: Chris@16: shared_lock_guard(shared_lock_guard const&); Chris@16: shared_lock_guard& operator= (shared_lock_guard const&); Chris@16: Chris@16: private: Chris@16: MutexT& m_Mutex; Chris@16: }; Chris@16: Chris@16: //! A deadlock-safe lock type that exclusively locks two mutexes Chris@16: template< typename MutexT1, typename MutexT2 > Chris@16: class multiple_unique_lock2 Chris@16: { Chris@16: public: Chris@16: multiple_unique_lock2(MutexT1& m1, MutexT2& m2) : Chris@16: m_p1(&m1), Chris@16: m_p2(&m2) Chris@16: { Chris@16: // Yes, it's not conforming, but it works Chris@16: // and it doesn't require to #include Chris@16: if (static_cast< void* >(m_p1) < static_cast< void* >(m_p2)) Chris@16: { Chris@16: m_p1->lock(); Chris@16: m_p2->lock(); Chris@16: } Chris@16: else Chris@16: { Chris@16: m_p2->lock(); Chris@16: m_p1->lock(); Chris@16: } Chris@16: } Chris@16: ~multiple_unique_lock2() Chris@16: { Chris@16: m_p2->unlock(); Chris@16: m_p1->unlock(); Chris@16: } Chris@16: Chris@16: private: Chris@16: MutexT1* m_p1; Chris@16: MutexT2* m_p2; Chris@16: }; Chris@16: Chris@16: #endif // BOOST_LOG_NO_THREADS Chris@16: Chris@16: } // namespace aux 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_DETAIL_LOCKS_HPP_INCLUDED_