summaryrefslogtreecommitdiff
path: root/boost/thread/v2/shared_mutex.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/thread/v2/shared_mutex.hpp')
-rw-r--r--boost/thread/v2/shared_mutex.hpp1168
1 files changed, 579 insertions, 589 deletions
diff --git a/boost/thread/v2/shared_mutex.hpp b/boost/thread/v2/shared_mutex.hpp
index 5e8b24f70a..e30a59e413 100644
--- a/boost/thread/v2/shared_mutex.hpp
+++ b/boost/thread/v2/shared_mutex.hpp
@@ -153,222 +153,292 @@ public:
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
+#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono.hpp>
+#endif
#include <climits>
#include <boost/system/system_error.hpp>
-#define BOOST_THREAD_INLINE inline
+#include <boost/bind.hpp>
namespace boost {
namespace thread_v2 {
class shared_mutex
{
- typedef ::boost::mutex mutex_t;
- typedef ::boost::condition_variable cond_t;
- typedef unsigned count_t;
+ typedef boost::mutex mutex_t;
+ typedef boost::condition_variable cond_t;
+ typedef unsigned count_t;
mutex_t mut_;
cond_t gate1_;
+ // the gate2_ condition variable is only used by functions that
+ // have taken write_entered_ but are waiting for no_readers()
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:
+ bool no_writer() const
+ {
+ return (state_ & write_entered_) == 0;
+ }
+
+ bool one_writer() const
+ {
+ return (state_ & write_entered_) != 0;
+ }
+
+ bool no_writer_no_readers() const
+ {
+ //return (state_ & write_entered_) == 0 &&
+ // (state_ & n_readers_) == 0;
+ return state_ == 0;
+ }
+
+ bool no_writer_no_max_readers() const
+ {
+ return (state_ & write_entered_) == 0 &&
+ (state_ & n_readers_) != n_readers_;
+ }
+
+ bool no_readers() const
+ {
+ return (state_ & n_readers_) == 0;
+ }
+
+ bool one_or_more_readers() const
+ {
+ return (state_ & n_readers_) > 0;
+ }
+
shared_mutex(shared_mutex const&);
shared_mutex& operator=(shared_mutex const&);
+
public:
-#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS
+ shared_mutex();
+ ~shared_mutex();
// Exclusive ownership
- BOOST_THREAD_INLINE void lock();
- BOOST_THREAD_INLINE bool try_lock();
+ void lock();
+ bool try_lock();
+#ifdef BOOST_THREAD_USES_CHRONO
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);
+ return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
- bool
- try_lock_until(
+ bool try_lock_until(
const boost::chrono::time_point<Clock, Duration>& abs_time);
- BOOST_THREAD_INLINE void unlock();
-
+#endif
+#if defined BOOST_THREAD_USES_DATETIME
+ template<typename T>
+ bool timed_lock(T const & abs_or_rel_time);
+#endif
+ void unlock();
// Shared ownership
- BOOST_THREAD_INLINE void lock_shared();
- BOOST_THREAD_INLINE bool try_lock_shared();
+ void lock_shared();
+ bool try_lock_shared();
+#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
- bool
- try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
+ 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);
+ return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
- bool
- try_lock_shared_until(
+ bool try_lock_shared_until(
const boost::chrono::time_point<Clock, Duration>& abs_time);
- BOOST_THREAD_INLINE void unlock_shared();
-
+#endif
#if defined BOOST_THREAD_USES_DATETIME
- bool timed_lock(system_time const& timeout);
- template<typename TimeDuration>
- bool timed_lock(TimeDuration const & relative_time)
+ template<typename T>
+ bool timed_lock_shared(T const & abs_or_rel_time);
+#endif
+ void unlock_shared();
+ };
+
+ inline shared_mutex::shared_mutex()
+ : state_(0)
+ {
+ }
+
+ inline shared_mutex::~shared_mutex()
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ }
+
+ // Exclusive ownership
+
+ inline void shared_mutex::lock()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ gate1_.wait(lk, boost::bind(&shared_mutex::no_writer, boost::ref(*this)));
+ state_ |= write_entered_;
+ gate2_.wait(lk, boost::bind(&shared_mutex::no_readers, boost::ref(*this)));
+ }
+
+ inline bool shared_mutex::try_lock()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (!no_writer_no_readers())
+ {
+ return false;
+ }
+ state_ = write_entered_;
+ return true;
+ }
+
+#ifdef BOOST_THREAD_USES_CHRONO
+ 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 (!gate1_.wait_until(lk, abs_time, boost::bind(
+ &shared_mutex::no_writer, boost::ref(*this))))
{
- return timed_lock(get_system_time()+relative_time);
+ return false;
}
- bool timed_lock_shared(system_time const& timeout);
- template<typename TimeDuration>
- bool timed_lock_shared(TimeDuration const & relative_time)
+ state_ |= write_entered_;
+ if (!gate2_.wait_until(lk, abs_time, boost::bind(
+ &shared_mutex::no_readers, boost::ref(*this))))
{
- return timed_lock_shared(get_system_time()+relative_time);
+ state_ &= ~write_entered_;
+ return false;
}
+ return true;
+ }
#endif
- };
- template <class Clock, class Duration>
- bool
- shared_mutex::try_lock_until(
- const boost::chrono::time_point<Clock, Duration>& abs_time)
+#if defined BOOST_THREAD_USES_DATETIME
+ template<typename T>
+ bool shared_mutex::timed_lock(T const & abs_or_rel_time)
{
boost::unique_lock<mutex_t> lk(mut_);
- if (state_ & write_entered_)
+ if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
+ &shared_mutex::no_writer, boost::ref(*this))))
{
- for (;;)
- {
- boost::cv_status status = gate1_.wait_until(lk, abs_time);
- if ((state_ & write_entered_) == 0)
- break;
- if (status == boost::cv_status::timeout)
- return false;
- }
+ return false;
}
state_ |= write_entered_;
- if (state_ & n_readers_)
+ if (!gate2_.timed_wait(lk, abs_or_rel_time, boost::bind(
+ &shared_mutex::no_readers, boost::ref(*this))))
+ {
+ state_ &= ~write_entered_;
+ return false;
+ }
+ return true;
+ }
+#endif
+
+ inline void shared_mutex::unlock()
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ BOOST_ASSERT(one_writer());
+ BOOST_ASSERT(no_readers());
+ state_ = 0;
+ // notify all since multiple *lock_shared*() calls may be able
+ // to proceed in response to this notification
+ gate1_.notify_all();
+ }
+
+ // Shared ownership
+
+ inline void shared_mutex::lock_shared()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ gate1_.wait(lk, boost::bind(&shared_mutex::no_writer_no_max_readers, boost::ref(*this)));
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ }
+
+ inline bool shared_mutex::try_lock_shared()
+ {
+ boost::unique_lock<mutex_t> lk(mut_);
+ if (!no_writer_no_max_readers())
{
- for (;;)
- {
- 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 false;
}
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
return true;
}
+#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration>
- bool
- shared_mutex::try_lock_shared_until(
+ 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_)
+ if (!gate1_.wait_until(lk, abs_time, boost::bind(
+ &shared_mutex::no_writer_no_max_readers, boost::ref(*this))))
{
- for (;;)
- {
- 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;
- }
+ return false;
}
count_t num_readers = (state_ & n_readers_) + 1;
state_ &= ~n_readers_;
state_ |= num_readers;
return true;
}
+#endif
#if defined BOOST_THREAD_USES_DATETIME
- bool shared_mutex::timed_lock(system_time const& abs_time)
+ template<typename T>
+ bool shared_mutex::timed_lock_shared(T const & abs_or_rel_time)
{
boost::unique_lock<mutex_t> lk(mut_);
- if (state_ & write_entered_)
- {
- for (;;)
- {
- 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_)
+ if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
+ &shared_mutex::no_writer_no_max_readers, boost::ref(*this))))
{
- for (;;)
- {
- bool status = gate2_.timed_wait(lk, abs_time);
- if ((state_ & n_readers_) == 0)
- break;
- if (!status)
- {
- state_ &= ~write_entered_;
- return false;
- }
- }
+ return false;
}
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
return true;
}
- bool shared_mutex::timed_lock_shared(system_time const& abs_time)
+#endif
+
+ inline void shared_mutex::unlock_shared()
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ BOOST_ASSERT(one_or_more_readers());
+ count_t num_readers = (state_ & n_readers_) - 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ if (no_writer())
{
- boost::unique_lock<mutex_t> lk(mut_);
- if (state_ & write_entered_)
- {
- for (;;)
- {
- 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_)
- {
- for (;;)
- {
- bool status = gate2_.timed_wait(lk, abs_time);
- if ((state_ & n_readers_) == 0)
- break;
- if (!status)
- {
- state_ &= ~write_entered_;
- return false;
- }
- }
- }
- return true;
+ if (num_readers == n_readers_ - 1)
+ gate1_.notify_one();
}
-#endif
+ else
+ {
+ if (num_readers == 0)
+ gate2_.notify_one();
+ }
+ }
+
+ } // thread_v2
+} // boost
+
+namespace boost {
+ namespace thread_v2 {
+
class upgrade_mutex
{
typedef boost::mutex mutex_t;
typedef boost::condition_variable cond_t;
- typedef unsigned count_t;
+ typedef unsigned count_t;
mutex_t mut_;
cond_t gate1_;
+ // the gate2_ condition variable is only used by functions that
+ // have taken write_entered_ but are waiting for no_readers()
cond_t gate2_;
count_t state_;
@@ -376,677 +446,597 @@ namespace boost {
static const unsigned upgradable_entered_ = write_entered_ >> 1;
static const unsigned n_readers_ = ~(write_entered_ | upgradable_entered_);
- public:
+ bool no_writer() const
+ {
+ return (state_ & write_entered_) == 0;
+ }
+
+ bool one_writer() const
+ {
+ return (state_ & write_entered_) != 0;
+ }
+
+ bool no_writer_no_max_readers() const
+ {
+ return (state_ & write_entered_) == 0 &&
+ (state_ & n_readers_) != n_readers_;
+ }
+
+ bool no_writer_no_upgrader() const
+ {
+ return (state_ & (write_entered_ | upgradable_entered_)) == 0;
+ }
+
+ bool no_writer_no_upgrader_no_readers() const
+ {
+ //return (state_ & (write_entered_ | upgradable_entered_)) == 0 &&
+ // (state_ & n_readers_) == 0;
+ return state_ == 0;
+ }
+
+ bool no_writer_no_upgrader_one_reader() const
+ {
+ //return (state_ & (write_entered_ | upgradable_entered_)) == 0 &&
+ // (state_ & n_readers_) == 1;
+ return state_ == 1;
+ }
+
+ bool no_writer_no_upgrader_no_max_readers() const
+ {
+ return (state_ & (write_entered_ | upgradable_entered_)) == 0 &&
+ (state_ & n_readers_) != n_readers_;
+ }
+
+ bool no_upgrader() const
+ {
+ return (state_ & upgradable_entered_) == 0;
+ }
+
+ bool one_upgrader() const
+ {
+ return (state_ & upgradable_entered_) != 0;
+ }
+
+ bool no_readers() const
+ {
+ return (state_ & n_readers_) == 0;
+ }
- BOOST_THREAD_INLINE upgrade_mutex();
- BOOST_THREAD_INLINE ~upgrade_mutex();
+ bool one_reader() const
+ {
+ return (state_ & n_readers_) == 1;
+ }
+
+ bool one_or_more_readers() const
+ {
+ return (state_ & n_readers_) > 0;
+ }
-#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
+ upgrade_mutex();
+ ~upgrade_mutex();
// Exclusive ownership
- BOOST_THREAD_INLINE void lock();
- BOOST_THREAD_INLINE bool try_lock();
+ void lock();
+ bool try_lock();
+#ifdef BOOST_THREAD_USES_CHRONO
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);
+ return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
- bool
- try_lock_until(
+ bool try_lock_until(
const boost::chrono::time_point<Clock, Duration>& abs_time);
- BOOST_THREAD_INLINE void unlock();
+#endif
+#if defined BOOST_THREAD_USES_DATETIME
+ template<typename T>
+ bool timed_lock(T const & abs_or_rel_time);
+#endif
+ void unlock();
// Shared ownership
- BOOST_THREAD_INLINE void lock_shared();
- BOOST_THREAD_INLINE bool try_lock_shared();
+ void lock_shared();
+ bool try_lock_shared();
+#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
- bool
- try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
+ 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);
+ return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
- bool
- try_lock_shared_until(
+ bool try_lock_shared_until(
const boost::chrono::time_point<Clock, Duration>& abs_time);
- BOOST_THREAD_INLINE void unlock_shared();
+#endif
+#if defined BOOST_THREAD_USES_DATETIME
+ template<typename T>
+ bool timed_lock_shared(T const & abs_or_rel_time);
+#endif
+ void unlock_shared();
// Upgrade ownership
- BOOST_THREAD_INLINE void lock_upgrade();
- BOOST_THREAD_INLINE bool try_lock_upgrade();
+ void lock_upgrade();
+ bool try_lock_upgrade();
+#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
- bool
- try_lock_upgrade_for(
+ 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);
+ return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
- bool
- try_lock_upgrade_until(
+ bool try_lock_upgrade_until(
const boost::chrono::time_point<Clock, Duration>& abs_time);
- BOOST_THREAD_INLINE void unlock_upgrade();
+#endif
+#if defined BOOST_THREAD_USES_DATETIME
+ template<typename T>
+ bool timed_lock_upgrade(T const & abs_or_rel_time);
+#endif
+ void unlock_upgrade();
// Shared <-> Exclusive
- BOOST_THREAD_INLINE bool try_unlock_shared_and_lock();
+#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+ //bool unlock_shared_and_lock(); // can cause a deadlock if used
+ bool try_unlock_shared_and_lock();
+#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
- bool
- try_unlock_shared_and_lock_for(
+ 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);
+ return try_unlock_shared_and_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
- bool
- try_unlock_shared_and_lock_until(
+ bool try_unlock_shared_and_lock_until(
const boost::chrono::time_point<Clock, Duration>& abs_time);
- BOOST_THREAD_INLINE void unlock_and_lock_shared();
+#endif
+#endif
+ void unlock_and_lock_shared();
// Shared <-> Upgrade
- BOOST_THREAD_INLINE bool try_unlock_shared_and_lock_upgrade();
+#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+ //bool unlock_shared_and_lock_upgrade(); // can cause a deadlock if used
+ bool try_unlock_shared_and_lock_upgrade();
+#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
- bool
- try_unlock_shared_and_lock_upgrade_for(
+ 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);
+ return try_unlock_shared_and_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
- bool
- try_unlock_shared_and_lock_upgrade_until(
+ 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();
+#endif
+#endif
+ 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();
+ void unlock_upgrade_and_lock();
+ bool try_unlock_upgrade_and_lock();
+#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
- bool
- try_unlock_upgrade_and_lock_for(
+ 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);
+ return try_unlock_upgrade_and_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
- bool
- try_unlock_upgrade_and_lock_until(
+ 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
-
+ void unlock_and_lock_upgrade();
};
- template <class Clock, class Duration>
- bool
- upgrade_mutex::try_lock_until(
- const boost::chrono::time_point<Clock, Duration>& abs_time)
+ inline upgrade_mutex::upgrade_mutex()
+ : gate1_(),
+ gate2_(),
+ state_(0)
{
- boost::unique_lock<mutex_t> lk(mut_);
- if (state_ & (write_entered_ | upgradable_entered_))
- {
- for (;;)
- {
- 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_)
- {
- for (;;)
- {
- 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)
+ inline upgrade_mutex::~upgrade_mutex()
{
- boost::unique_lock<mutex_t> lk(mut_);
- if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
- {
- for (;;)
- {
- 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;
+ boost::lock_guard<mutex_t> _(mut_);
}
- template <class Clock, class Duration>
- bool
- upgrade_mutex::try_lock_upgrade_until(
- const boost::chrono::time_point<Clock, Duration>& abs_time)
+ // Exclusive ownership
+
+ inline void upgrade_mutex::lock()
{
boost::unique_lock<mutex_t> lk(mut_);
- if ((state_ & (write_entered_ | upgradable_entered_)) ||
- (state_ & n_readers_) == n_readers_)
- {
- for (;;)
- {
- 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;
+ gate1_.wait(lk, boost::bind(&upgrade_mutex::no_writer_no_upgrader, boost::ref(*this)));
+ state_ |= write_entered_;
+ gate2_.wait(lk, boost::bind(&upgrade_mutex::no_readers, boost::ref(*this)));
}
-#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_))
- {
- for (;;)
- {
- 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_)
- {
- for (;;)
- {
- 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_)
- {
- for (;;)
- {
- 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_)
- {
- for (;;)
- {
- 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)
+ inline bool upgrade_mutex::try_lock()
{
boost::unique_lock<mutex_t> lk(mut_);
- if (state_ != 1)
+ if (!no_writer_no_upgrader_no_readers())
{
- for (;;)
- {
- boost::cv_status status = gate2_.wait_until(lk, abs_time);
- if (state_ == 1)
- break;
- if (status == boost::cv_status::timeout)
- return false;
- }
+ return false;
}
state_ = write_entered_;
return true;
}
+#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration>
- bool
- upgrade_mutex::try_unlock_shared_and_lock_upgrade_until(
+ 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_)) != 0)
+ if (!gate1_.wait_until(lk, abs_time, boost::bind(
+ &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
{
- for (;;)
- {
- 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;
- }
+ return false;
+ }
+ state_ |= write_entered_;
+ if (!gate2_.wait_until(lk, abs_time, boost::bind(
+ &upgrade_mutex::no_readers, boost::ref(*this))))
+ {
+ state_ &= ~write_entered_;
+ return false;
}
- state_ |= upgradable_entered_;
return true;
}
+#endif
- template <class Clock, class Duration>
- bool
- upgrade_mutex::try_unlock_upgrade_and_lock_until(
- const boost::chrono::time_point<Clock, Duration>& abs_time)
+#if defined BOOST_THREAD_USES_DATETIME
+ template<typename T>
+ bool upgrade_mutex::timed_lock(T const & abs_or_rel_time)
{
boost::unique_lock<mutex_t> lk(mut_);
- if ((state_ & n_readers_) != 1)
+ if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
+ &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
{
- for (;;)
- {
- boost::cv_status status = gate2_.wait_until(lk, abs_time);
- if ((state_ & n_readers_) == 1)
- break;
- if (status == boost::cv_status::timeout)
- return false;
- }
+ return false;
+ }
+ state_ |= write_entered_;
+ if (!gate2_.timed_wait(lk, abs_or_rel_time, boost::bind(
+ &upgrade_mutex::no_readers, boost::ref(*this))))
+ {
+ state_ &= ~write_entered_;
+ return false;
}
- state_ = write_entered_;
return true;
}
+#endif
- //////
- // shared_mutex
-
- shared_mutex::shared_mutex()
- : state_(0)
- {
- }
-
- shared_mutex::~shared_mutex()
+ inline void upgrade_mutex::unlock()
{
boost::lock_guard<mutex_t> _(mut_);
+ BOOST_ASSERT(one_writer());
+ BOOST_ASSERT(no_upgrader());
+ BOOST_ASSERT(no_readers());
+ state_ = 0;
+ // notify all since multiple *lock_shared*() calls and a *lock_upgrade*()
+ // call may be able to proceed in response to this notification
+ gate1_.notify_all();
}
- // Exclusive ownership
+ // Shared ownership
- void
- shared_mutex::lock()
+ inline void upgrade_mutex::lock_shared()
{
boost::unique_lock<mutex_t> lk(mut_);
- while (state_ & write_entered_)
- gate1_.wait(lk);
- state_ |= write_entered_;
- while (state_ & n_readers_)
- gate2_.wait(lk);
+ gate1_.wait(lk, boost::bind(&upgrade_mutex::no_writer_no_max_readers, boost::ref(*this)));
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
}
- bool
- shared_mutex::try_lock()
+ inline bool upgrade_mutex::try_lock_shared()
{
boost::unique_lock<mutex_t> lk(mut_);
- if (state_ == 0)
+ if (!no_writer_no_max_readers())
{
- state_ = write_entered_;
- return true;
+ return false;
}
- return false;
- }
-
- void
- shared_mutex::unlock()
- {
- boost::lock_guard<mutex_t> _(mut_);
- state_ = 0;
- gate1_.notify_all();
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ return true;
}
- // Shared ownership
-
- void
- shared_mutex::lock_shared()
+#ifdef BOOST_THREAD_USES_CHRONO
+ 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_);
- while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
- gate1_.wait(lk);
+ if (!gate1_.wait_until(lk, abs_time, boost::bind(
+ &upgrade_mutex::no_writer_no_max_readers, boost::ref(*this))))
+ {
+ return false;
+ }
count_t num_readers = (state_ & n_readers_) + 1;
state_ &= ~n_readers_;
state_ |= num_readers;
+ return true;
}
+#endif
- bool
- shared_mutex::try_lock_shared()
+#if defined BOOST_THREAD_USES_DATETIME
+ template<typename T>
+ bool upgrade_mutex::timed_lock_shared(T const & abs_or_rel_time)
{
boost::unique_lock<mutex_t> lk(mut_);
- count_t num_readers = state_ & n_readers_;
- if (!(state_ & write_entered_) && num_readers != n_readers_)
+ if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
+ &upgrade_mutex::no_writer_no_max_readers, boost::ref(*this))))
{
- ++num_readers;
- state_ &= ~n_readers_;
- state_ |= num_readers;
- return true;
+ return false;
}
- return false;
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= num_readers;
+ return true;
}
+#endif
- void
- shared_mutex::unlock_shared()
+ inline void upgrade_mutex::unlock_shared()
{
boost::lock_guard<mutex_t> _(mut_);
+ BOOST_ASSERT(one_or_more_readers());
count_t num_readers = (state_ & n_readers_) - 1;
state_ &= ~n_readers_;
state_ |= num_readers;
- if (state_ & write_entered_)
+ if (no_writer())
{
- if (num_readers == 0)
- gate2_.notify_one();
+ if (num_readers == n_readers_ - 1)
+ gate1_.notify_one();
}
else
{
- if (num_readers == n_readers_ - 1)
- gate1_.notify_one();
+ if (num_readers == 0)
+ gate2_.notify_one();
}
}
- // upgrade_mutex
-
- upgrade_mutex::upgrade_mutex()
- : gate1_(),
- gate2_(),
- state_(0)
- {
- }
-
- upgrade_mutex::~upgrade_mutex()
- {
- boost::lock_guard<mutex_t> _(mut_);
- }
-
- // Exclusive ownership
+ // Upgrade ownership
- void
- upgrade_mutex::lock()
+ inline void upgrade_mutex::lock_upgrade()
{
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);
+ gate1_.wait(lk, boost::bind(&upgrade_mutex::no_writer_no_upgrader_no_max_readers, boost::ref(*this)));
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= upgradable_entered_ | num_readers;
}
- bool
- upgrade_mutex::try_lock()
+ inline bool upgrade_mutex::try_lock_upgrade()
{
boost::unique_lock<mutex_t> lk(mut_);
- if (state_ == 0)
+ if (!no_writer_no_upgrader_no_max_readers())
{
- state_ = write_entered_;
- return true;
+ return false;
}
- return false;
- }
-
- void
- upgrade_mutex::unlock()
- {
- boost::lock_guard<mutex_t> _(mut_);
- state_ = 0;
- gate1_.notify_all();
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= upgradable_entered_ | num_readers;
+ return true;
}
- // Shared ownership
-
- void
- upgrade_mutex::lock_shared()
+#ifdef BOOST_THREAD_USES_CHRONO
+ 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_);
- while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
- gate1_.wait(lk);
+ if (!gate1_.wait_until(lk, abs_time, boost::bind(
+ &upgrade_mutex::no_writer_no_upgrader_no_max_readers, boost::ref(*this))))
+ {
+ return false;
+ }
count_t num_readers = (state_ & n_readers_) + 1;
state_ &= ~n_readers_;
- state_ |= num_readers;
+ state_ |= upgradable_entered_ | num_readers;
+ return true;
}
+#endif
- bool
- upgrade_mutex::try_lock_shared()
+#if defined BOOST_THREAD_USES_DATETIME
+ template<typename T>
+ bool upgrade_mutex::timed_lock_upgrade(T const & abs_or_rel_time)
{
boost::unique_lock<mutex_t> lk(mut_);
- count_t num_readers = state_ & n_readers_;
- if (!(state_ & write_entered_) && num_readers != n_readers_)
+ if (!gate1_.timed_wait(lk, abs_or_rel_time, boost::bind(
+ &upgrade_mutex::no_writer_no_upgrader_no_max_readers, boost::ref(*this))))
{
- ++num_readers;
- state_ &= ~n_readers_;
- state_ |= num_readers;
- return true;
+ return false;
}
- return false;
+ count_t num_readers = (state_ & n_readers_) + 1;
+ state_ &= ~n_readers_;
+ state_ |= upgradable_entered_ | num_readers;
+ return true;
}
+#endif
- void
- upgrade_mutex::unlock_shared()
+ inline void upgrade_mutex::unlock_upgrade()
{
boost::lock_guard<mutex_t> _(mut_);
+ BOOST_ASSERT(no_writer());
+ BOOST_ASSERT(one_upgrader());
+ BOOST_ASSERT(one_or_more_readers());
count_t num_readers = (state_ & n_readers_) - 1;
- state_ &= ~n_readers_;
+ state_ &= ~(upgradable_entered_ | 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();
- }
+ // notify all since both a *lock*() and a *lock_shared*() call
+ // may be able to proceed in response to this notification
+ gate1_.notify_all();
}
- // Upgrade ownership
+ // Shared <-> Exclusive
- void
- upgrade_mutex::lock_upgrade()
+#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+ inline bool upgrade_mutex::try_unlock_shared_and_lock()
{
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;
+ BOOST_ASSERT(one_or_more_readers());
+ if (!no_writer_no_upgrader_one_reader())
+ {
+ return false;
+ }
+ state_ = write_entered_;
+ return true;
}
- bool
- upgrade_mutex::try_lock_upgrade()
+#ifdef BOOST_THREAD_USES_CHRONO
+ 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_);
- count_t num_readers = state_ & n_readers_;
- if (!(state_ & (write_entered_ | upgradable_entered_))
- && num_readers != n_readers_)
+ BOOST_ASSERT(one_or_more_readers());
+ if (!gate1_.wait_until(lk, abs_time, boost::bind(
+ &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
+ {
+ return false;
+ }
+ count_t num_readers = (state_ & n_readers_) - 1;
+ state_ &= ~n_readers_;
+ state_ |= (write_entered_ | num_readers);
+ if (!gate2_.wait_until(lk, abs_time, boost::bind(
+ &upgrade_mutex::no_readers, boost::ref(*this))))
{
++num_readers;
- state_ &= ~n_readers_;
- state_ |= upgradable_entered_ | num_readers;
- return true;
+ state_ &= ~(write_entered_ | n_readers_);
+ state_ |= num_readers;
+ return false;
}
- return false;
+ return true;
}
+#endif
+#endif
- void
- upgrade_mutex::unlock_upgrade()
+ inline void upgrade_mutex::unlock_and_lock_shared()
{
- {
- boost::lock_guard<mutex_t> _(mut_);
- count_t num_readers = (state_ & n_readers_) - 1;
- state_ &= ~(upgradable_entered_ | n_readers_);
- state_ |= num_readers;
- }
+ boost::lock_guard<mutex_t> _(mut_);
+ BOOST_ASSERT(one_writer());
+ BOOST_ASSERT(no_upgrader());
+ BOOST_ASSERT(no_readers());
+ state_ = 1;
+ // notify all since multiple *lock_shared*() calls and a *lock_upgrade*()
+ // call may be able to proceed in response to this notification
gate1_.notify_all();
}
- // Shared <-> Exclusive
+ // Shared <-> Upgrade
- bool
- upgrade_mutex::try_unlock_shared_and_lock()
+#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
+ inline bool upgrade_mutex::try_unlock_shared_and_lock_upgrade()
{
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_ASSERT(one_or_more_readers());
+ if (!no_writer_no_upgrader())
{
- boost::lock_guard<mutex_t> _(mut_);
- state_ = 1;
+ return false;
}
- gate1_.notify_all();
+ state_ |= upgradable_entered_;
+ return true;
}
- // Shared <-> Upgrade
-
- bool
- upgrade_mutex::try_unlock_shared_and_lock_upgrade()
+#ifdef BOOST_THREAD_USES_CHRONO
+ 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_)))
+ BOOST_ASSERT(one_or_more_readers());
+ if (!gate1_.wait_until(lk, abs_time, boost::bind(
+ &upgrade_mutex::no_writer_no_upgrader, boost::ref(*this))))
{
- state_ |= upgradable_entered_;
- return true;
+ return false;
}
- return false;
+ state_ |= upgradable_entered_;
+ return true;
}
+#endif
+#endif
- void
- upgrade_mutex::unlock_upgrade_and_lock_shared()
+ inline void upgrade_mutex::unlock_upgrade_and_lock_shared()
{
- {
- boost::lock_guard<mutex_t> _(mut_);
- state_ &= ~upgradable_entered_;
- }
+ boost::lock_guard<mutex_t> _(mut_);
+ BOOST_ASSERT(no_writer());
+ BOOST_ASSERT(one_upgrader());
+ BOOST_ASSERT(one_or_more_readers());
+ state_ &= ~upgradable_entered_;
+ // notify all since only one *lock*() or *lock_upgrade*() call can win and
+ // proceed in response to this notification, but a *lock_shared*() call may
+ // also be waiting and could steal the notification
gate1_.notify_all();
}
// Upgrade <-> Exclusive
- void
- upgrade_mutex::unlock_upgrade_and_lock()
+ inline void upgrade_mutex::unlock_upgrade_and_lock()
{
boost::unique_lock<mutex_t> lk(mut_);
+ BOOST_ASSERT(no_writer());
+ BOOST_ASSERT(one_upgrader());
+ BOOST_ASSERT(one_or_more_readers());
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);
+ gate2_.wait(lk, boost::bind(&upgrade_mutex::no_readers, boost::ref(*this)));
}
- bool
- upgrade_mutex::try_unlock_upgrade_and_lock()
+ inline bool upgrade_mutex::try_unlock_upgrade_and_lock()
{
boost::unique_lock<mutex_t> lk(mut_);
- if (state_ == (upgradable_entered_ | 1))
+ BOOST_ASSERT(no_writer());
+ BOOST_ASSERT(one_upgrader());
+ BOOST_ASSERT(one_or_more_readers());
+ if (!one_reader())
{
- state_ = write_entered_;
- return true;
+ return false;
}
- return false;
+ state_ = write_entered_;
+ return true;
}
- void
- upgrade_mutex::unlock_and_lock_upgrade()
+#ifdef BOOST_THREAD_USES_CHRONO
+ 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_);
+ BOOST_ASSERT(no_writer());
+ BOOST_ASSERT(one_upgrader());
+ BOOST_ASSERT(one_or_more_readers());
+ count_t num_readers = (state_ & n_readers_) - 1;
+ state_ &= ~(upgradable_entered_ | n_readers_);
+ state_ |= (write_entered_ | num_readers);
+ if (!gate2_.wait_until(lk, abs_time, boost::bind(
+ &upgrade_mutex::no_readers, boost::ref(*this))))
{
- boost::lock_guard<mutex_t> _(mut_);
- state_ = upgradable_entered_ | 1;
+ ++num_readers;
+ state_ &= ~(write_entered_ | n_readers_);
+ state_ |= (upgradable_entered_ | num_readers);
+ return false;
}
+ return true;
+ }
+#endif
+
+ inline void upgrade_mutex::unlock_and_lock_upgrade()
+ {
+ boost::lock_guard<mutex_t> _(mut_);
+ BOOST_ASSERT(one_writer());
+ BOOST_ASSERT(no_upgrader());
+ BOOST_ASSERT(no_readers());
+ state_ = upgradable_entered_ | 1;
+ // notify all since multiple *lock_shared*() calls may be able
+ // to proceed in response to this notification
gate1_.notify_all();
}