summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp')
-rw-r--r--3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp287
1 files changed, 226 insertions, 61 deletions
diff --git a/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp
index cf45188..458d6c8 100644
--- a/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp
+++ b/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp
@@ -12,12 +12,15 @@
#include <boost/static_assert.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
#include <boost/thread/detail/thread_interruption.hpp>
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
+#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -26,8 +29,125 @@ namespace boost
class shared_mutex
{
private:
- struct state_data
+ class state_data
{
+ public:
+ state_data () :
+ shared_count(0),
+ exclusive(false),
+ upgrade(false),
+ exclusive_waiting_blocked(false)
+ {}
+
+ void assert_free() const
+ {
+ BOOST_ASSERT( ! exclusive );
+ BOOST_ASSERT( ! upgrade );
+ BOOST_ASSERT( shared_count==0 );
+ }
+
+ void assert_locked() const
+ {
+ BOOST_ASSERT( exclusive );
+ BOOST_ASSERT( shared_count==0 );
+ BOOST_ASSERT( ! upgrade );
+ }
+
+ void assert_lock_shared () const
+ {
+ BOOST_ASSERT( ! exclusive );
+ BOOST_ASSERT( shared_count>0 );
+ //BOOST_ASSERT( (! upgrade) || (shared_count>1));
+ // if upgraded there are at least 2 threads sharing the mutex,
+ // except when unlock_upgrade_and_lock has decreased the number of readers but has not taken yet exclusive ownership.
+ }
+
+ void assert_lock_upgraded () const
+ {
+ BOOST_ASSERT( ! exclusive );
+ BOOST_ASSERT( upgrade );
+ BOOST_ASSERT( shared_count>0 );
+ }
+
+ void assert_lock_not_upgraded () const
+ {
+ BOOST_ASSERT( ! upgrade );
+ }
+
+ bool can_lock () const
+ {
+ return ! (shared_count || exclusive);
+ }
+
+ void exclusive_blocked (bool blocked)
+ {
+ exclusive_waiting_blocked = blocked;
+ }
+
+ void lock ()
+ {
+ exclusive = true;
+ }
+
+ void unlock ()
+ {
+ exclusive = false;
+ exclusive_waiting_blocked = false;
+ }
+
+ bool can_lock_shared () const
+ {
+ return ! (exclusive || exclusive_waiting_blocked);
+ }
+
+ bool more_shared () const
+ {
+ return shared_count > 0 ;
+ }
+ unsigned get_shared_count () const
+ {
+ return shared_count ;
+ }
+ unsigned lock_shared ()
+ {
+ return ++shared_count;
+ }
+
+
+ void unlock_shared ()
+ {
+ --shared_count;
+ }
+
+ bool unlock_shared_downgrades()
+ {
+ if (upgrade) {
+ upgrade=false;
+ exclusive=true;
+ return true;
+ } else {
+ exclusive_waiting_blocked=false;
+ return false;
+ }
+ }
+
+ void lock_upgrade ()
+ {
+ ++shared_count;
+ upgrade=true;
+ }
+ bool can_lock_upgrade () const
+ {
+ return ! (exclusive || exclusive_waiting_blocked || upgrade);
+ }
+
+ void unlock_upgrade ()
+ {
+ upgrade=false;
+ --shared_count;
+ }
+
+ //private:
unsigned shared_count;
bool exclusive;
bool upgrade;
@@ -49,12 +169,11 @@ namespace boost
}
public:
+
BOOST_THREAD_NO_COPYABLE(shared_mutex)
shared_mutex()
{
- state_data state_={0,0,0,0};
- state=state_;
}
~shared_mutex()
@@ -63,44 +182,45 @@ namespace boost
void lock_shared()
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
-
- while(state.exclusive || state.exclusive_waiting_blocked)
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ while(!state.can_lock_shared())
{
shared_cond.wait(lk);
}
- ++state.shared_count;
+ state.lock_shared();
}
bool try_lock_shared()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
- if(state.exclusive || state.exclusive_waiting_blocked)
+ if(!state.can_lock_shared())
{
return false;
}
- else
- {
- ++state.shared_count;
- return true;
- }
+ state.lock_shared();
+ return true;
}
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock_shared(system_time const& timeout)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
- while(state.exclusive || state.exclusive_waiting_blocked)
+ while(!state.can_lock_shared())
{
if(!shared_cond.timed_wait(lk,timeout))
{
return false;
}
}
- ++state.shared_count;
+ state.lock_shared();
return true;
}
@@ -109,6 +229,7 @@ namespace boost
{
return timed_lock_shared(get_system_time()+relative_time);
}
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
@@ -118,36 +239,43 @@ namespace boost
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
- while(state.exclusive || state.exclusive_waiting_blocked)
+ while(!state.can_lock_shared())
+ //while(state.exclusive || state.exclusive_waiting_blocked)
{
if(cv_status::timeout==shared_cond.wait_until(lk,abs_time))
{
return false;
}
}
- ++state.shared_count;
+ state.lock_shared();
return true;
}
#endif
void unlock_shared()
{
- boost::mutex::scoped_lock lk(state_change);
- bool const last_reader=!--state.shared_count;
-
- if(last_reader)
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
+ state.unlock_shared();
+ if (! state.more_shared())
{
- if(state.upgrade)
+ if (state.upgrade)
{
+ // As there is a thread doing a unlock_upgrade_and_lock that is waiting for ! state.more_shared()
+ // avoid other threads to lock, lock_upgrade or lock_shared, so only this thread is notified.
state.upgrade=false;
state.exclusive=true;
+ lk.unlock();
upgrade_cond.notify_one();
}
else
{
state.exclusive_waiting_blocked=false;
+ lk.unlock();
}
release_waiters();
}
@@ -155,10 +283,12 @@ namespace boost
void lock()
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
- while(state.shared_count || state.exclusive)
+ while (state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
exclusive_cond.wait(lk);
@@ -166,10 +296,13 @@ namespace boost
state.exclusive=true;
}
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(system_time const& timeout)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
while(state.shared_count || state.exclusive)
{
@@ -194,7 +327,7 @@ namespace boost
{
return timed_lock(get_system_time()+relative_time);
}
-
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
@@ -204,8 +337,10 @@ namespace boost
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
while(state.shared_count || state.exclusive)
{
@@ -228,7 +363,7 @@ namespace boost
bool try_lock()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
if(state.shared_count || state.exclusive)
{
@@ -244,28 +379,35 @@ namespace boost
void unlock()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_locked();
state.exclusive=false;
state.exclusive_waiting_blocked=false;
+ state.assert_free();
release_waiters();
}
void lock_upgrade()
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
shared_cond.wait(lk);
}
- ++state.shared_count;
+ state.lock_shared();
state.upgrade=true;
}
+#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock_upgrade(system_time const& timeout)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
if(!shared_cond.timed_wait(lk,timeout))
@@ -277,7 +419,7 @@ namespace boost
break;
}
}
- ++state.shared_count;
+ state.lock_shared();
state.upgrade=true;
return true;
}
@@ -287,7 +429,7 @@ namespace boost
{
return timed_lock_upgrade(get_system_time()+relative_time);
}
-
+#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time)
@@ -297,8 +439,10 @@ namespace boost
template <class Clock, class Duration>
bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
if(cv_status::timeout == shared_cond.wait_until(lk,abs_time))
@@ -310,68 +454,75 @@ namespace boost
break;
}
}
- ++state.shared_count;
+ state.lock_shared();
state.upgrade=true;
return true;
}
#endif
bool try_lock_upgrade()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
}
else
{
- ++state.shared_count;
+ state.lock_shared();
state.upgrade=true;
+ state.assert_lock_upgraded();
return true;
}
}
void unlock_upgrade()
{
- boost::mutex::scoped_lock lk(state_change);
- state.upgrade=false;
- bool const last_reader=!--state.shared_count;
-
- if(last_reader)
+ boost::unique_lock<boost::mutex> lk(state_change);
+ //state.upgrade=false;
+ state.unlock_upgrade();
+ if(! state.more_shared() )
{
state.exclusive_waiting_blocked=false;
release_waiters();
} else {
- shared_cond.notify_all();
+ shared_cond.notify_all();
}
}
// Upgrade <-> Exclusive
void unlock_upgrade_and_lock()
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
- --state.shared_count;
- while(state.shared_count)
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
+ state.unlock_shared();
+ while (state.more_shared())
{
upgrade_cond.wait(lk);
}
state.upgrade=false;
state.exclusive=true;
+ state.assert_locked();
}
void unlock_and_lock_upgrade()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_locked();
state.exclusive=false;
state.upgrade=true;
- ++state.shared_count;
+ state.lock_shared();
state.exclusive_waiting_blocked=false;
+ state.assert_lock_upgraded();
release_waiters();
}
bool try_unlock_upgrade_and_lock()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& state.upgrade
@@ -380,6 +531,7 @@ namespace boost
state.shared_count=0;
state.exclusive=true;
state.upgrade=false;
+ state.assert_locked();
return true;
}
return false;
@@ -398,8 +550,11 @@ namespace boost
try_unlock_upgrade_and_lock_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
if (state.shared_count != 1)
{
for (;;)
@@ -422,9 +577,10 @@ namespace boost
// Shared <-> Exclusive
void unlock_and_lock_shared()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_locked();
state.exclusive=false;
- ++state.shared_count;
+ state.lock_shared();
state.exclusive_waiting_blocked=false;
release_waiters();
}
@@ -432,7 +588,8 @@ namespace boost
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& !state.upgrade
@@ -458,8 +615,11 @@ namespace boost
try_unlock_shared_and_lock_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
if (state.shared_count != 1)
{
for (;;)
@@ -483,7 +643,8 @@ namespace boost
// Shared <-> Upgrade
void unlock_upgrade_and_lock_shared()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_upgraded();
state.upgrade=false;
state.exclusive_waiting_blocked=false;
release_waiters();
@@ -492,7 +653,8 @@ namespace boost
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock_upgrade()
{
- boost::mutex::scoped_lock lk(state_change);
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& !state.upgrade
@@ -517,8 +679,11 @@ namespace boost
try_unlock_shared_and_lock_upgrade_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
- boost::mutex::scoped_lock lk(state_change);
+#endif
+ boost::unique_lock<boost::mutex> lk(state_change);
+ state.assert_lock_shared();
if( state.exclusive
|| state.exclusive_waiting_blocked
|| state.upgrade