locks.hpp 5.9 KB

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