conditionally_enabled_mutex.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. //
  2. // detail/conditionally_enabled_mutex.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2021 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. mutex_.mutex_.lock();
  65. locked_ = true;
  66. }
  67. }
  68. // Explicitly release the lock.
  69. void unlock()
  70. {
  71. if (locked_)
  72. {
  73. mutex_.unlock();
  74. locked_ = false;
  75. }
  76. }
  77. // Test whether the lock is held.
  78. bool locked() const
  79. {
  80. return locked_;
  81. }
  82. // Get the underlying mutex.
  83. boost::asio::detail::mutex& mutex()
  84. {
  85. return mutex_.mutex_;
  86. }
  87. private:
  88. friend class conditionally_enabled_event;
  89. conditionally_enabled_mutex& mutex_;
  90. bool locked_;
  91. };
  92. // Constructor.
  93. explicit conditionally_enabled_mutex(bool enabled)
  94. : enabled_(enabled)
  95. {
  96. }
  97. // Destructor.
  98. ~conditionally_enabled_mutex()
  99. {
  100. }
  101. // Determine whether locking is enabled.
  102. bool enabled() const
  103. {
  104. return enabled_;
  105. }
  106. // Lock the mutex.
  107. void lock()
  108. {
  109. if (enabled_)
  110. mutex_.lock();
  111. }
  112. // Unlock the mutex.
  113. void unlock()
  114. {
  115. if (enabled_)
  116. mutex_.unlock();
  117. }
  118. private:
  119. friend class scoped_lock;
  120. friend class conditionally_enabled_event;
  121. boost::asio::detail::mutex mutex_;
  122. const bool enabled_;
  123. };
  124. } // namespace detail
  125. } // namespace asio
  126. } // namespace boost
  127. #include <boost/asio/detail/pop_options.hpp>
  128. #endif // BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP