summaryrefslogtreecommitdiff
path: root/boost/thread/v2/shared_mutex.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/thread/v2/shared_mutex.hpp')
-rwxr-xr-xboost/thread/v2/shared_mutex.hpp1062
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