diff options
Diffstat (limited to '3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp | 287 |
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 |