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