conditionally_enabled_mutex.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. //
  2. // detail/conditionally_enabled_mutex.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP
  11. #define BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <boost/asio/detail/mutex.hpp>
  17. #include <boost/asio/detail/noncopyable.hpp>
  18. #include <boost/asio/detail/scoped_lock.hpp>
  19. #include <boost/asio/detail/push_options.hpp>
  20. namespace boost {
  21. namespace asio {
  22. namespace detail {
  23. // Mutex adapter used to conditionally enable or disable locking.
  24. class conditionally_enabled_mutex
  25. : private noncopyable
  26. {
  27. public:
  28. // Helper class to lock and unlock a mutex automatically.
  29. class scoped_lock
  30. : private noncopyable
  31. {
  32. public:
  33. // Tag type used to distinguish constructors.
  34. enum adopt_lock_t { adopt_lock };
  35. // Constructor adopts a lock that is already held.
  36. scoped_lock(conditionally_enabled_mutex& m, adopt_lock_t)
  37. : mutex_(m),
  38. locked_(m.enabled_)
  39. {
  40. }
  41. // Constructor acquires the lock.
  42. explicit scoped_lock(conditionally_enabled_mutex& m)
  43. : mutex_(m)
  44. {
  45. if (m.enabled_)
  46. {
  47. mutex_.mutex_.lock();
  48. locked_ = true;
  49. }
  50. else
  51. locked_ = false;
  52. }
  53. // Destructor releases the lock.
  54. ~scoped_lock()
  55. {
  56. if (locked_)
  57. mutex_.mutex_.unlock();
  58. }
  59. // Explicitly acquire the lock.
  60. void lock()
  61. {
  62. if (mutex_.enabled_ && !locked_)
  63. {
  64. for (int n = mutex_.spin_count_; n != 0; n -= (n > 0) ? 1 : 0)
  65. {
  66. if (mutex_.mutex_.try_lock())
  67. {
  68. locked_ = true;
  69. return;
  70. }
  71. }
  72. mutex_.mutex_.lock();
  73. locked_ = true;
  74. }
  75. }
  76. // Explicitly release the lock.
  77. void unlock()
  78. {
  79. if (locked_)
  80. {
  81. mutex_.unlock();
  82. locked_ = false;
  83. }
  84. }
  85. // Test whether the lock is held.
  86. bool locked() const
  87. {
  88. return locked_;
  89. }
  90. // Get the underlying mutex.
  91. boost::asio::detail::mutex& mutex()
  92. {
  93. return mutex_.mutex_;
  94. }
  95. private:
  96. friend class conditionally_enabled_event;
  97. conditionally_enabled_mutex& mutex_;
  98. bool locked_;
  99. };
  100. // Constructor.
  101. explicit conditionally_enabled_mutex(bool enabled, int spin_count = 0)
  102. : spin_count_(spin_count),
  103. enabled_(enabled)
  104. {
  105. }
  106. // Destructor.
  107. ~conditionally_enabled_mutex()
  108. {
  109. }
  110. // Determine whether locking is enabled.
  111. bool enabled() const
  112. {
  113. return enabled_;
  114. }
  115. // Get the spin count.
  116. int spin_count() const
  117. {
  118. return spin_count_;
  119. }
  120. // Lock the mutex.
  121. void lock()
  122. {
  123. if (enabled_)
  124. {
  125. for (int n = spin_count_; n != 0; n -= (n > 0) ? 1 : 0)
  126. if (mutex_.try_lock())
  127. return;
  128. mutex_.lock();
  129. }
  130. }
  131. // Unlock the mutex.
  132. void unlock()
  133. {
  134. if (enabled_)
  135. mutex_.unlock();
  136. }
  137. private:
  138. friend class scoped_lock;
  139. friend class conditionally_enabled_event;
  140. boost::asio::detail::mutex mutex_;
  141. const int spin_count_;
  142. const bool enabled_;
  143. };
  144. } // namespace detail
  145. } // namespace asio
  146. } // namespace boost
  147. #include <boost/asio/detail/pop_options.hpp>
  148. #endif // BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP