locks.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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 locks.hpp
  9. * \author Andrey Semashev
  10. * \date 30.05.2010
  11. *
  12. * \brief This header is the Boost.Log library implementation, see the library documentation
  13. * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
  14. */
  15. #ifndef BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_
  16. #define BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_
  17. #include <boost/log/detail/config.hpp>
  18. #include <boost/log/detail/header.hpp>
  19. #ifdef BOOST_HAS_PRAGMA_ONCE
  20. #pragma once
  21. #endif
  22. namespace boost {
  23. #ifndef BOOST_LOG_NO_THREADS
  24. // Forward declaration of Boost.Thread locks. Specified here to avoid including Boost.Thread,
  25. // which would bring in many dependent headers, including a great deal of Boost.DateTime.
  26. template< typename >
  27. class lock_guard;
  28. template< typename >
  29. class shared_lock_guard;
  30. template< typename >
  31. class shared_lock;
  32. template< typename >
  33. class upgrade_lock;
  34. template< typename >
  35. class unique_lock;
  36. template< typename >
  37. struct is_mutex_type;
  38. #endif // BOOST_LOG_NO_THREADS
  39. BOOST_LOG_OPEN_NAMESPACE
  40. //! An auxiliary pseudo-lock to express no locking requirements in logger features
  41. template< typename MutexT >
  42. class no_lock
  43. {
  44. public:
  45. /*!
  46. * Constructs the pseudo-lock. The mutex is not affected during the construction.
  47. */
  48. explicit no_lock(MutexT&) {}
  49. private:
  50. no_lock(no_lock const&);
  51. no_lock& operator= (no_lock const&);
  52. };
  53. namespace aux {
  54. #ifndef BOOST_LOG_NO_THREADS
  55. //! A trait to detect if the mutex supports exclusive locking
  56. template< typename MutexT >
  57. struct is_exclusively_lockable
  58. {
  59. typedef char true_type;
  60. struct false_type { char t[2]; };
  61. template< typename T >
  62. static true_type check_lockable(T*, void (T::*)() = &T::lock, void (T::*)() = &T::unlock);
  63. static false_type check_lockable(void*);
  64. enum value_t { value = sizeof(check_lockable((MutexT*)NULL)) == sizeof(true_type) };
  65. };
  66. //! A trait to detect if the mutex supports shared locking
  67. template< typename MutexT >
  68. struct is_shared_lockable
  69. {
  70. typedef char true_type;
  71. struct false_type { char t[2]; };
  72. template< typename T >
  73. static true_type check_shared_lockable(T*, void (T::*)() = &T::lock_shared, void (T::*)() = &T::unlock_shared);
  74. static false_type check_shared_lockable(void*);
  75. enum value_t { value = sizeof(check_shared_lockable((MutexT*)NULL)) == sizeof(true_type) };
  76. };
  77. //! A scope guard that automatically unlocks the mutex on destruction
  78. template< typename MutexT >
  79. struct exclusive_auto_unlocker
  80. {
  81. explicit exclusive_auto_unlocker(MutexT& m) BOOST_NOEXCEPT : m_Mutex(m)
  82. {
  83. }
  84. ~exclusive_auto_unlocker()
  85. {
  86. m_Mutex.unlock();
  87. }
  88. BOOST_DELETED_FUNCTION(exclusive_auto_unlocker(exclusive_auto_unlocker const&))
  89. BOOST_DELETED_FUNCTION(exclusive_auto_unlocker& operator= (exclusive_auto_unlocker const&))
  90. protected:
  91. MutexT& m_Mutex;
  92. };
  93. //! An analogue to the minimalistic \c lock_guard template. Defined here to avoid including Boost.Thread.
  94. template< typename MutexT >
  95. struct exclusive_lock_guard
  96. {
  97. explicit exclusive_lock_guard(MutexT& m) : m_Mutex(m)
  98. {
  99. m.lock();
  100. }
  101. ~exclusive_lock_guard()
  102. {
  103. m_Mutex.unlock();
  104. }
  105. BOOST_DELETED_FUNCTION(exclusive_lock_guard(exclusive_lock_guard const&))
  106. BOOST_DELETED_FUNCTION(exclusive_lock_guard& operator= (exclusive_lock_guard const&))
  107. private:
  108. MutexT& m_Mutex;
  109. };
  110. //! An analogue to the minimalistic \c lock_guard template that locks \c shared_mutex with shared ownership.
  111. template< typename MutexT >
  112. struct shared_lock_guard
  113. {
  114. explicit shared_lock_guard(MutexT& m) : m_Mutex(m)
  115. {
  116. m.lock_shared();
  117. }
  118. ~shared_lock_guard()
  119. {
  120. m_Mutex.unlock_shared();
  121. }
  122. BOOST_DELETED_FUNCTION(shared_lock_guard(shared_lock_guard const&))
  123. BOOST_DELETED_FUNCTION(shared_lock_guard& operator= (shared_lock_guard const&))
  124. private:
  125. MutexT& m_Mutex;
  126. };
  127. //! A deadlock-safe lock type that exclusively locks two mutexes
  128. template< typename MutexT1, typename MutexT2 >
  129. class multiple_unique_lock2
  130. {
  131. public:
  132. multiple_unique_lock2(MutexT1& m1, MutexT2& m2) :
  133. m_p1(&m1),
  134. m_p2(&m2)
  135. {
  136. // Yes, it's not conforming, but it works
  137. // and it doesn't require to #include <functional>
  138. if (static_cast< void* >(m_p1) < static_cast< void* >(m_p2))
  139. {
  140. m_p1->lock();
  141. m_p2->lock();
  142. }
  143. else
  144. {
  145. m_p2->lock();
  146. m_p1->lock();
  147. }
  148. }
  149. ~multiple_unique_lock2()
  150. {
  151. m_p2->unlock();
  152. m_p1->unlock();
  153. }
  154. private:
  155. MutexT1* m_p1;
  156. MutexT2* m_p2;
  157. };
  158. #endif // BOOST_LOG_NO_THREADS
  159. } // namespace aux
  160. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  161. } // namespace boost
  162. #include <boost/log/detail/footer.hpp>
  163. #endif // BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_