Chris@16: #ifndef BOOST_THREAD_V2_SHARED_MUTEX_HPP Chris@16: #define BOOST_THREAD_V2_SHARED_MUTEX_HPP Chris@16: Chris@16: // shared_mutex.hpp Chris@16: // Chris@16: // Copyright Howard Hinnant 2007-2010. Chris@16: // Copyright Vicente J. Botet Escriba 2012. Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: /* Chris@16: synopsis Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: namespace thread_v2 Chris@16: { Chris@16: Chris@16: class shared_mutex Chris@16: { Chris@16: public: Chris@16: Chris@16: shared_mutex(); Chris@16: ~shared_mutex(); Chris@16: Chris@16: shared_mutex(const shared_mutex&) = delete; Chris@16: shared_mutex& operator=(const shared_mutex&) = delete; Chris@16: Chris@16: // Exclusive ownership Chris@16: Chris@16: void lock(); Chris@16: bool try_lock(); Chris@16: template Chris@16: bool try_lock_for(const boost::chrono::duration& rel_time); Chris@16: template Chris@16: bool Chris@16: try_lock_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: void unlock(); Chris@16: Chris@16: // Shared ownership Chris@16: Chris@16: void lock_shared(); Chris@16: bool try_lock_shared(); Chris@16: template Chris@16: bool Chris@16: try_lock_shared_for(const boost::chrono::duration& rel_time); Chris@16: template Chris@16: bool Chris@16: try_lock_shared_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: void unlock_shared(); Chris@16: }; Chris@16: Chris@16: class upgrade_mutex Chris@16: { Chris@16: public: Chris@16: Chris@16: upgrade_mutex(); Chris@16: ~upgrade_mutex(); Chris@16: Chris@16: upgrade_mutex(const upgrade_mutex&) = delete; Chris@16: upgrade_mutex& operator=(const upgrade_mutex&) = delete; Chris@16: Chris@16: // Exclusive ownership Chris@16: Chris@16: void lock(); Chris@16: bool try_lock(); Chris@16: template Chris@16: bool try_lock_for(const boost::chrono::duration& rel_time); Chris@16: template Chris@16: bool Chris@16: try_lock_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: void unlock(); Chris@16: Chris@16: // Shared ownership Chris@16: Chris@16: void lock_shared(); Chris@16: bool try_lock_shared(); Chris@16: template Chris@16: bool Chris@16: try_lock_shared_for(const boost::chrono::duration& rel_time); Chris@16: template Chris@16: bool Chris@16: try_lock_shared_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: void unlock_shared(); Chris@16: Chris@16: // Upgrade ownership Chris@16: Chris@16: void lock_upgrade(); Chris@16: bool try_lock_upgrade(); Chris@16: template Chris@16: bool Chris@16: try_lock_upgrade_for( Chris@16: const boost::chrono::duration& rel_time); Chris@16: template Chris@16: bool Chris@16: try_lock_upgrade_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: void unlock_upgrade(); Chris@16: Chris@16: // Shared <-> Exclusive Chris@16: Chris@16: bool try_unlock_shared_and_lock(); Chris@16: template Chris@16: bool Chris@16: try_unlock_shared_and_lock_for( Chris@16: const boost::chrono::duration& rel_time); Chris@16: template Chris@16: bool Chris@16: try_unlock_shared_and_lock_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: void unlock_and_lock_shared(); Chris@16: Chris@16: // Shared <-> Upgrade Chris@16: Chris@16: bool try_unlock_shared_and_lock_upgrade(); Chris@16: template Chris@16: bool Chris@16: try_unlock_shared_and_lock_upgrade_for( Chris@16: const boost::chrono::duration& rel_time); Chris@16: template Chris@16: bool Chris@16: try_unlock_shared_and_lock_upgrade_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: void unlock_upgrade_and_lock_shared(); Chris@16: Chris@16: // Upgrade <-> Exclusive Chris@16: Chris@16: void unlock_upgrade_and_lock(); Chris@16: bool try_unlock_upgrade_and_lock(); Chris@16: template Chris@16: bool Chris@16: try_unlock_upgrade_and_lock_for( Chris@16: const boost::chrono::duration& rel_time); Chris@16: template Chris@16: bool Chris@16: try_unlock_upgrade_and_lock_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: void unlock_and_lock_upgrade(); Chris@16: }; Chris@16: Chris@16: } // thread_v2 Chris@16: } // boost Chris@16: Chris@16: */ Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #define BOOST_THREAD_INLINE inline Chris@16: Chris@16: namespace boost { Chris@16: namespace thread_v2 { Chris@16: Chris@16: class shared_mutex Chris@16: { Chris@16: typedef ::boost::mutex mutex_t; Chris@16: typedef ::boost::condition_variable cond_t; Chris@16: typedef unsigned count_t; Chris@16: Chris@16: mutex_t mut_; Chris@16: cond_t gate1_; Chris@16: cond_t gate2_; Chris@16: count_t state_; Chris@16: Chris@16: static const count_t write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1); Chris@16: static const count_t n_readers_ = ~write_entered_; Chris@16: Chris@16: public: Chris@16: BOOST_THREAD_INLINE shared_mutex(); Chris@16: BOOST_THREAD_INLINE ~shared_mutex(); Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS Chris@16: shared_mutex(shared_mutex const&) = delete; Chris@16: shared_mutex& operator=(shared_mutex const&) = delete; Chris@16: #else // BOOST_NO_CXX11_DELETED_FUNCTIONS Chris@16: private: Chris@16: shared_mutex(shared_mutex const&); Chris@16: shared_mutex& operator=(shared_mutex const&); Chris@16: public: Chris@16: #endif // BOOST_NO_CXX11_DELETED_FUNCTIONS Chris@16: Chris@16: // Exclusive ownership Chris@16: Chris@16: BOOST_THREAD_INLINE void lock(); Chris@16: BOOST_THREAD_INLINE bool try_lock(); Chris@16: template Chris@16: bool try_lock_for(const boost::chrono::duration& rel_time) Chris@16: { Chris@16: return try_lock_until(boost::chrono::steady_clock::now() + rel_time); Chris@16: } Chris@16: template Chris@16: bool Chris@16: try_lock_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: BOOST_THREAD_INLINE void unlock(); Chris@16: Chris@16: Chris@16: // Shared ownership Chris@16: Chris@16: BOOST_THREAD_INLINE void lock_shared(); Chris@16: BOOST_THREAD_INLINE bool try_lock_shared(); Chris@16: template Chris@16: bool Chris@16: try_lock_shared_for(const boost::chrono::duration& rel_time) Chris@16: { Chris@16: return try_lock_shared_until(boost::chrono::steady_clock::now() + Chris@16: rel_time); Chris@16: } Chris@16: template Chris@16: bool Chris@16: try_lock_shared_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: BOOST_THREAD_INLINE void unlock_shared(); Chris@16: Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: bool timed_lock(system_time const& timeout); Chris@16: template Chris@16: bool timed_lock(TimeDuration const & relative_time) Chris@16: { Chris@16: return timed_lock(get_system_time()+relative_time); Chris@16: } Chris@16: bool timed_lock_shared(system_time const& timeout); Chris@16: template Chris@16: bool timed_lock_shared(TimeDuration const & relative_time) Chris@16: { Chris@16: return timed_lock_shared(get_system_time()+relative_time); Chris@16: } Chris@16: #endif Chris@16: }; Chris@16: Chris@16: template Chris@16: bool Chris@16: shared_mutex::try_lock_until( Chris@16: const boost::chrono::time_point& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if (state_ & write_entered_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: boost::cv_status status = gate1_.wait_until(lk, abs_time); Chris@16: if ((state_ & write_entered_) == 0) Chris@16: break; Chris@16: if (status == boost::cv_status::timeout) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: state_ |= write_entered_; Chris@16: if (state_ & n_readers_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: boost::cv_status status = gate2_.wait_until(lk, abs_time); Chris@16: if ((state_ & n_readers_) == 0) Chris@16: break; Chris@16: if (status == boost::cv_status::timeout) Chris@16: { Chris@16: state_ &= ~write_entered_; Chris@16: return false; Chris@16: } Chris@16: } Chris@16: } Chris@16: return true; Chris@16: } Chris@16: Chris@16: template Chris@16: bool Chris@16: shared_mutex::try_lock_shared_until( Chris@16: const boost::chrono::time_point& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: boost::cv_status status = gate1_.wait_until(lk, abs_time); Chris@16: if ((state_ & write_entered_) == 0 && Chris@16: (state_ & n_readers_) < n_readers_) Chris@16: break; Chris@16: if (status == boost::cv_status::timeout) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: count_t num_readers = (state_ & n_readers_) + 1; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= num_readers; Chris@16: return true; Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: bool shared_mutex::timed_lock(system_time const& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if (state_ & write_entered_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: bool status = gate1_.timed_wait(lk, abs_time); Chris@16: if ((state_ & write_entered_) == 0) Chris@16: break; Chris@16: if (!status) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: state_ |= write_entered_; Chris@16: if (state_ & n_readers_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: bool status = gate2_.timed_wait(lk, abs_time); Chris@16: if ((state_ & n_readers_) == 0) Chris@16: break; Chris@16: if (!status) Chris@16: { Chris@16: state_ &= ~write_entered_; Chris@16: return false; Chris@16: } Chris@16: } Chris@16: } Chris@16: return true; Chris@16: } Chris@16: bool shared_mutex::timed_lock_shared(system_time const& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if (state_ & write_entered_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: bool status = gate1_.timed_wait(lk, abs_time); Chris@16: if ((state_ & write_entered_) == 0) Chris@16: break; Chris@16: if (!status ) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: state_ |= write_entered_; Chris@16: if (state_ & n_readers_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: bool status = gate2_.timed_wait(lk, abs_time); Chris@16: if ((state_ & n_readers_) == 0) Chris@16: break; Chris@16: if (!status) Chris@16: { Chris@16: state_ &= ~write_entered_; Chris@16: return false; Chris@16: } Chris@16: } Chris@16: } Chris@16: return true; Chris@16: } Chris@16: #endif Chris@16: class upgrade_mutex Chris@16: { Chris@16: typedef boost::mutex mutex_t; Chris@16: typedef boost::condition_variable cond_t; Chris@16: typedef unsigned count_t; Chris@16: Chris@16: mutex_t mut_; Chris@16: cond_t gate1_; Chris@16: cond_t gate2_; Chris@16: count_t state_; Chris@16: Chris@16: static const unsigned write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1); Chris@16: static const unsigned upgradable_entered_ = write_entered_ >> 1; Chris@16: static const unsigned n_readers_ = ~(write_entered_ | upgradable_entered_); Chris@16: Chris@16: public: Chris@16: Chris@16: BOOST_THREAD_INLINE upgrade_mutex(); Chris@16: BOOST_THREAD_INLINE ~upgrade_mutex(); Chris@16: Chris@16: #ifndef BOOST_CXX11_NO_DELETED_FUNCTIONS Chris@16: upgrade_mutex(const upgrade_mutex&) = delete; Chris@16: upgrade_mutex& operator=(const upgrade_mutex&) = delete; Chris@16: #else // BOOST_CXX11_NO_DELETED_FUNCTIONS Chris@16: private: Chris@16: upgrade_mutex(const upgrade_mutex&); Chris@16: upgrade_mutex& operator=(const upgrade_mutex&); Chris@16: public: Chris@16: #endif // BOOST_CXX11_NO_DELETED_FUNCTIONS Chris@16: Chris@16: // Exclusive ownership Chris@16: Chris@16: BOOST_THREAD_INLINE void lock(); Chris@16: BOOST_THREAD_INLINE bool try_lock(); Chris@16: template Chris@16: bool try_lock_for(const boost::chrono::duration& rel_time) Chris@16: { Chris@16: return try_lock_until(boost::chrono::steady_clock::now() + rel_time); Chris@16: } Chris@16: template Chris@16: bool Chris@16: try_lock_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: BOOST_THREAD_INLINE void unlock(); Chris@16: Chris@16: // Shared ownership Chris@16: Chris@16: BOOST_THREAD_INLINE void lock_shared(); Chris@16: BOOST_THREAD_INLINE bool try_lock_shared(); Chris@16: template Chris@16: bool Chris@16: try_lock_shared_for(const boost::chrono::duration& rel_time) Chris@16: { Chris@16: return try_lock_shared_until(boost::chrono::steady_clock::now() + Chris@16: rel_time); Chris@16: } Chris@16: template Chris@16: bool Chris@16: try_lock_shared_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: BOOST_THREAD_INLINE void unlock_shared(); Chris@16: Chris@16: // Upgrade ownership Chris@16: Chris@16: BOOST_THREAD_INLINE void lock_upgrade(); Chris@16: BOOST_THREAD_INLINE bool try_lock_upgrade(); Chris@16: template Chris@16: bool Chris@16: try_lock_upgrade_for( Chris@16: const boost::chrono::duration& rel_time) Chris@16: { Chris@16: return try_lock_upgrade_until(boost::chrono::steady_clock::now() + Chris@16: rel_time); Chris@16: } Chris@16: template Chris@16: bool Chris@16: try_lock_upgrade_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: BOOST_THREAD_INLINE void unlock_upgrade(); Chris@16: Chris@16: // Shared <-> Exclusive Chris@16: Chris@16: BOOST_THREAD_INLINE bool try_unlock_shared_and_lock(); Chris@16: template Chris@16: bool Chris@16: try_unlock_shared_and_lock_for( Chris@16: const boost::chrono::duration& rel_time) Chris@16: { Chris@16: return try_unlock_shared_and_lock_until( Chris@16: boost::chrono::steady_clock::now() + rel_time); Chris@16: } Chris@16: template Chris@16: bool Chris@16: try_unlock_shared_and_lock_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: BOOST_THREAD_INLINE void unlock_and_lock_shared(); Chris@16: Chris@16: // Shared <-> Upgrade Chris@16: Chris@16: BOOST_THREAD_INLINE bool try_unlock_shared_and_lock_upgrade(); Chris@16: template Chris@16: bool Chris@16: try_unlock_shared_and_lock_upgrade_for( Chris@16: const boost::chrono::duration& rel_time) Chris@16: { Chris@16: return try_unlock_shared_and_lock_upgrade_until( Chris@16: boost::chrono::steady_clock::now() + rel_time); Chris@16: } Chris@16: template Chris@16: bool Chris@16: try_unlock_shared_and_lock_upgrade_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: BOOST_THREAD_INLINE void unlock_upgrade_and_lock_shared(); Chris@16: Chris@16: // Upgrade <-> Exclusive Chris@16: Chris@16: BOOST_THREAD_INLINE void unlock_upgrade_and_lock(); Chris@16: BOOST_THREAD_INLINE bool try_unlock_upgrade_and_lock(); Chris@16: template Chris@16: bool Chris@16: try_unlock_upgrade_and_lock_for( Chris@16: const boost::chrono::duration& rel_time) Chris@16: { Chris@16: return try_unlock_upgrade_and_lock_until( Chris@16: boost::chrono::steady_clock::now() + rel_time); Chris@16: } Chris@16: template Chris@16: bool Chris@16: try_unlock_upgrade_and_lock_until( Chris@16: const boost::chrono::time_point& abs_time); Chris@16: BOOST_THREAD_INLINE void unlock_and_lock_upgrade(); Chris@16: Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: inline bool timed_lock(system_time const& abs_time); Chris@16: template Chris@16: bool timed_lock(TimeDuration const & relative_time) Chris@16: { Chris@16: return timed_lock(get_system_time()+relative_time); Chris@16: } Chris@16: inline bool timed_lock_shared(system_time const& abs_time); Chris@16: template Chris@16: bool timed_lock_shared(TimeDuration const & relative_time) Chris@16: { Chris@16: return timed_lock_shared(get_system_time()+relative_time); Chris@16: } Chris@16: inline bool timed_lock_upgrade(system_time const& abs_time); Chris@16: template Chris@16: bool timed_lock_upgrade(TimeDuration const & relative_time) Chris@16: { Chris@16: return timed_lock_upgrade(get_system_time()+relative_time); Chris@16: } Chris@16: #endif Chris@16: Chris@16: }; Chris@16: Chris@16: template Chris@16: bool Chris@16: upgrade_mutex::try_lock_until( Chris@16: const boost::chrono::time_point& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if (state_ & (write_entered_ | upgradable_entered_)) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: boost::cv_status status = gate1_.wait_until(lk, abs_time); Chris@16: if ((state_ & (write_entered_ | upgradable_entered_)) == 0) Chris@16: break; Chris@16: if (status == boost::cv_status::timeout) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: state_ |= write_entered_; Chris@16: if (state_ & n_readers_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: boost::cv_status status = gate2_.wait_until(lk, abs_time); Chris@16: if ((state_ & n_readers_) == 0) Chris@16: break; Chris@16: if (status == boost::cv_status::timeout) Chris@16: { Chris@16: state_ &= ~write_entered_; Chris@16: return false; Chris@16: } Chris@16: } Chris@16: } Chris@16: return true; Chris@16: } Chris@16: Chris@16: template Chris@16: bool Chris@16: upgrade_mutex::try_lock_shared_until( Chris@16: const boost::chrono::time_point& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: boost::cv_status status = gate1_.wait_until(lk, abs_time); Chris@16: if ((state_ & write_entered_) == 0 && Chris@16: (state_ & n_readers_) < n_readers_) Chris@16: break; Chris@16: if (status == boost::cv_status::timeout) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: count_t num_readers = (state_ & n_readers_) + 1; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= num_readers; Chris@16: return true; Chris@16: } Chris@16: Chris@16: template Chris@16: bool Chris@16: upgrade_mutex::try_lock_upgrade_until( Chris@16: const boost::chrono::time_point& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if ((state_ & (write_entered_ | upgradable_entered_)) || Chris@16: (state_ & n_readers_) == n_readers_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: boost::cv_status status = gate1_.wait_until(lk, abs_time); Chris@16: if ((state_ & (write_entered_ | upgradable_entered_)) == 0 && Chris@16: (state_ & n_readers_) < n_readers_) Chris@16: break; Chris@16: if (status == boost::cv_status::timeout) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: count_t num_readers = (state_ & n_readers_) + 1; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= upgradable_entered_ | num_readers; Chris@16: return true; Chris@16: } Chris@16: Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: bool upgrade_mutex::timed_lock(system_time const& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if (state_ & (write_entered_ | upgradable_entered_)) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: bool status = gate1_.timed_wait(lk, abs_time); Chris@16: if ((state_ & (write_entered_ | upgradable_entered_)) == 0) Chris@16: break; Chris@16: if (!status) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: state_ |= write_entered_; Chris@16: if (state_ & n_readers_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: bool status = gate2_.timed_wait(lk, abs_time); Chris@16: if ((state_ & n_readers_) == 0) Chris@16: break; Chris@16: if (!status) Chris@16: { Chris@16: state_ &= ~write_entered_; Chris@16: return false; Chris@16: } Chris@16: } Chris@16: } Chris@16: return true; Chris@16: } Chris@16: bool upgrade_mutex::timed_lock_shared(system_time const& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: bool status = gate1_.timed_wait(lk, abs_time); Chris@16: if ((state_ & write_entered_) == 0 && Chris@16: (state_ & n_readers_) < n_readers_) Chris@16: break; Chris@16: if (!status) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: count_t num_readers = (state_ & n_readers_) + 1; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= num_readers; Chris@16: return true; Chris@16: } Chris@16: bool upgrade_mutex::timed_lock_upgrade(system_time const& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if ((state_ & (write_entered_ | upgradable_entered_)) || Chris@16: (state_ & n_readers_) == n_readers_) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: bool status = gate1_.timed_wait(lk, abs_time); Chris@16: if ((state_ & (write_entered_ | upgradable_entered_)) == 0 && Chris@16: (state_ & n_readers_) < n_readers_) Chris@16: break; Chris@16: if (!status) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: count_t num_readers = (state_ & n_readers_) + 1; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= upgradable_entered_ | num_readers; Chris@16: return true; Chris@16: } Chris@16: Chris@16: #endif Chris@16: template Chris@16: bool Chris@16: upgrade_mutex::try_unlock_shared_and_lock_until( Chris@16: const boost::chrono::time_point& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if (state_ != 1) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: boost::cv_status status = gate2_.wait_until(lk, abs_time); Chris@16: if (state_ == 1) Chris@16: break; Chris@16: if (status == boost::cv_status::timeout) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: state_ = write_entered_; Chris@16: return true; Chris@16: } Chris@16: Chris@16: template Chris@16: bool Chris@16: upgrade_mutex::try_unlock_shared_and_lock_upgrade_until( Chris@16: const boost::chrono::time_point& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if ((state_ & (write_entered_ | upgradable_entered_)) != 0) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: boost::cv_status status = gate2_.wait_until(lk, abs_time); Chris@16: if ((state_ & (write_entered_ | upgradable_entered_)) == 0) Chris@16: break; Chris@16: if (status == boost::cv_status::timeout) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: state_ |= upgradable_entered_; Chris@16: return true; Chris@16: } Chris@16: Chris@16: template Chris@16: bool Chris@16: upgrade_mutex::try_unlock_upgrade_and_lock_until( Chris@16: const boost::chrono::time_point& abs_time) Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if ((state_ & n_readers_) != 1) Chris@16: { Chris@16: while (true) Chris@16: { Chris@16: boost::cv_status status = gate2_.wait_until(lk, abs_time); Chris@16: if ((state_ & n_readers_) == 1) Chris@16: break; Chris@16: if (status == boost::cv_status::timeout) Chris@16: return false; Chris@16: } Chris@16: } Chris@16: state_ = write_entered_; Chris@16: return true; Chris@16: } Chris@16: Chris@16: ////// Chris@16: // shared_mutex Chris@16: Chris@16: shared_mutex::shared_mutex() Chris@16: : state_(0) Chris@16: { Chris@16: } Chris@16: Chris@16: shared_mutex::~shared_mutex() Chris@16: { Chris@16: boost::lock_guard _(mut_); Chris@16: } Chris@16: Chris@16: // Exclusive ownership Chris@16: Chris@16: void Chris@16: shared_mutex::lock() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: while (state_ & write_entered_) Chris@16: gate1_.wait(lk); Chris@16: state_ |= write_entered_; Chris@16: while (state_ & n_readers_) Chris@16: gate2_.wait(lk); Chris@16: } Chris@16: Chris@16: bool Chris@16: shared_mutex::try_lock() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if (state_ == 0) Chris@16: { Chris@16: state_ = write_entered_; Chris@16: return true; Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: void Chris@16: shared_mutex::unlock() Chris@16: { Chris@16: boost::lock_guard _(mut_); Chris@16: state_ = 0; Chris@16: gate1_.notify_all(); Chris@16: } Chris@16: Chris@16: // Shared ownership Chris@16: Chris@16: void Chris@16: shared_mutex::lock_shared() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_) Chris@16: gate1_.wait(lk); Chris@16: count_t num_readers = (state_ & n_readers_) + 1; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= num_readers; Chris@16: } Chris@16: Chris@16: bool Chris@16: shared_mutex::try_lock_shared() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: count_t num_readers = state_ & n_readers_; Chris@16: if (!(state_ & write_entered_) && num_readers != n_readers_) Chris@16: { Chris@16: ++num_readers; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= num_readers; Chris@16: return true; Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: void Chris@16: shared_mutex::unlock_shared() Chris@16: { Chris@16: boost::lock_guard _(mut_); Chris@16: count_t num_readers = (state_ & n_readers_) - 1; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= num_readers; Chris@16: if (state_ & write_entered_) Chris@16: { Chris@16: if (num_readers == 0) Chris@16: gate2_.notify_one(); Chris@16: } Chris@16: else Chris@16: { Chris@16: if (num_readers == n_readers_ - 1) Chris@16: gate1_.notify_one(); Chris@16: } Chris@16: } Chris@16: Chris@16: // upgrade_mutex Chris@16: Chris@16: upgrade_mutex::upgrade_mutex() Chris@16: : gate1_(), Chris@16: gate2_(), Chris@16: state_(0) Chris@16: { Chris@16: } Chris@16: Chris@16: upgrade_mutex::~upgrade_mutex() Chris@16: { Chris@16: boost::lock_guard _(mut_); Chris@16: } Chris@16: Chris@16: // Exclusive ownership Chris@16: Chris@16: void Chris@16: upgrade_mutex::lock() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: while (state_ & (write_entered_ | upgradable_entered_)) Chris@16: gate1_.wait(lk); Chris@16: state_ |= write_entered_; Chris@16: while (state_ & n_readers_) Chris@16: gate2_.wait(lk); Chris@16: } Chris@16: Chris@16: bool Chris@16: upgrade_mutex::try_lock() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if (state_ == 0) Chris@16: { Chris@16: state_ = write_entered_; Chris@16: return true; Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: void Chris@16: upgrade_mutex::unlock() Chris@16: { Chris@16: boost::lock_guard _(mut_); Chris@16: state_ = 0; Chris@16: gate1_.notify_all(); Chris@16: } Chris@16: Chris@16: // Shared ownership Chris@16: Chris@16: void Chris@16: upgrade_mutex::lock_shared() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_) Chris@16: gate1_.wait(lk); Chris@16: count_t num_readers = (state_ & n_readers_) + 1; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= num_readers; Chris@16: } Chris@16: Chris@16: bool Chris@16: upgrade_mutex::try_lock_shared() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: count_t num_readers = state_ & n_readers_; Chris@16: if (!(state_ & write_entered_) && num_readers != n_readers_) Chris@16: { Chris@16: ++num_readers; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= num_readers; Chris@16: return true; Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: void Chris@16: upgrade_mutex::unlock_shared() Chris@16: { Chris@16: boost::lock_guard _(mut_); Chris@16: count_t num_readers = (state_ & n_readers_) - 1; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= num_readers; Chris@16: if (state_ & write_entered_) Chris@16: { Chris@16: if (num_readers == 0) Chris@16: gate2_.notify_one(); Chris@16: } Chris@16: else Chris@16: { Chris@16: if (num_readers == n_readers_ - 1) Chris@16: gate1_.notify_one(); Chris@16: } Chris@16: } Chris@16: Chris@16: // Upgrade ownership Chris@16: Chris@16: void Chris@16: upgrade_mutex::lock_upgrade() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: while ((state_ & (write_entered_ | upgradable_entered_)) || Chris@16: (state_ & n_readers_) == n_readers_) Chris@16: gate1_.wait(lk); Chris@16: count_t num_readers = (state_ & n_readers_) + 1; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= upgradable_entered_ | num_readers; Chris@16: } Chris@16: Chris@16: bool Chris@16: upgrade_mutex::try_lock_upgrade() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: count_t num_readers = state_ & n_readers_; Chris@16: if (!(state_ & (write_entered_ | upgradable_entered_)) Chris@16: && num_readers != n_readers_) Chris@16: { Chris@16: ++num_readers; Chris@16: state_ &= ~n_readers_; Chris@16: state_ |= upgradable_entered_ | num_readers; Chris@16: return true; Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: void Chris@16: upgrade_mutex::unlock_upgrade() Chris@16: { Chris@16: { Chris@16: boost::lock_guard _(mut_); Chris@16: count_t num_readers = (state_ & n_readers_) - 1; Chris@16: state_ &= ~(upgradable_entered_ | n_readers_); Chris@16: state_ |= num_readers; Chris@16: } Chris@16: gate1_.notify_all(); Chris@16: } Chris@16: Chris@16: // Shared <-> Exclusive Chris@16: Chris@16: bool Chris@16: upgrade_mutex::try_unlock_shared_and_lock() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if (state_ == 1) Chris@16: { Chris@16: state_ = write_entered_; Chris@16: return true; Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: void Chris@16: upgrade_mutex::unlock_and_lock_shared() Chris@16: { Chris@16: { Chris@16: boost::lock_guard _(mut_); Chris@16: state_ = 1; Chris@16: } Chris@16: gate1_.notify_all(); Chris@16: } Chris@16: Chris@16: // Shared <-> Upgrade Chris@16: Chris@16: bool Chris@16: upgrade_mutex::try_unlock_shared_and_lock_upgrade() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if (!(state_ & (write_entered_ | upgradable_entered_))) Chris@16: { Chris@16: state_ |= upgradable_entered_; Chris@16: return true; Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: void Chris@16: upgrade_mutex::unlock_upgrade_and_lock_shared() Chris@16: { Chris@16: { Chris@16: boost::lock_guard _(mut_); Chris@16: state_ &= ~upgradable_entered_; Chris@16: } Chris@16: gate1_.notify_all(); Chris@16: } Chris@16: Chris@16: // Upgrade <-> Exclusive Chris@16: Chris@16: void Chris@16: upgrade_mutex::unlock_upgrade_and_lock() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: count_t num_readers = (state_ & n_readers_) - 1; Chris@16: state_ &= ~(upgradable_entered_ | n_readers_); Chris@16: state_ |= write_entered_ | num_readers; Chris@16: while (state_ & n_readers_) Chris@16: gate2_.wait(lk); Chris@16: } Chris@16: Chris@16: bool Chris@16: upgrade_mutex::try_unlock_upgrade_and_lock() Chris@16: { Chris@16: boost::unique_lock lk(mut_); Chris@16: if (state_ == (upgradable_entered_ | 1)) Chris@16: { Chris@16: state_ = write_entered_; Chris@16: return true; Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: void Chris@16: upgrade_mutex::unlock_and_lock_upgrade() Chris@16: { Chris@16: { Chris@16: boost::lock_guard _(mut_); Chris@16: state_ = upgradable_entered_ | 1; Chris@16: } Chris@16: gate1_.notify_all(); Chris@16: } Chris@16: Chris@16: } // thread_v2 Chris@16: } // boost Chris@16: Chris@16: namespace boost { Chris@16: //using thread_v2::shared_mutex; Chris@16: using thread_v2::upgrade_mutex; Chris@16: typedef thread_v2::upgrade_mutex shared_mutex; Chris@16: } Chris@16: Chris@16: #endif