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