Index: boost/thread/pthread/shared_mutex.hpp =================================================================== --- boost/thread/pthread/shared_mutex.hpp (revision 82432) +++ boost/thread/pthread/shared_mutex.hpp (working copy) @@ -28,18 +28,96 @@ class shared_mutex { private: - struct state_data + class state_data { + public: + state_data () : + shared_count(0), exclusive(false), upgrade(false), exclusive_waiting_blocked(false) { + } + + bool can_lock () const { + if (shared_count || exclusive) + return false; + + return true; + } + + 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 { + if (exclusive || exclusive_waiting_blocked) + return false; + + return true; + } + + bool last_shared () const { + return shared_count == 1; + } + + unsigned lock_shared () { + return ++shared_count; + } + + unsigned unlock_shared () { + bool const last_reader = !--shared_count; + + if (last_reader) { + if (upgrade) { + upgrade=false; + exclusive=true; + } else { + exclusive_waiting_blocked=false; + } + } + + return shared_count; + } + + bool can_lock_upgrade () const { + if (exclusive || exclusive_waiting_blocked || upgrade) + return false; + + return true; + } + + void lock_upgrade () { + ++shared_count; + upgrade=true; + } + + unsigned unlock_upgrade () { + upgrade=false; + bool const last_reader=!--shared_count; + + if (last_reader) + exclusive_waiting_blocked=false; + + return shared_count; + } + + private: unsigned shared_count; - bool exclusive; - bool upgrade; - bool exclusive_waiting_blocked; + bool exclusive; + bool upgrade; + bool exclusive_waiting_blocked; }; - state_data state; - boost::mutex state_change; + state_data state; + boost::mutex state_change; boost::condition_variable shared_cond; boost::condition_variable exclusive_cond; boost::condition_variable upgrade_cond; @@ -55,8 +133,6 @@ shared_mutex() { - state_data state_={0,0,0,0}; - state=state_; } ~shared_mutex() @@ -70,26 +146,21 @@ #endif boost::unique_lock lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked) - { + while(!state.can_lock_shared()) shared_cond.wait(lk); - } - ++state.shared_count; + + state.lock_shared(); } bool try_lock_shared() { boost::unique_lock 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 @@ -100,14 +171,12 @@ #endif boost::unique_lock lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked) - { - if(!shared_cond.timed_wait(lk,timeout)) - { + while (!state.can_lock_shared()) { + if (!shared_cond.timed_wait(lk,timeout)) return false; - } } - ++state.shared_count; + + state.lock_shared(); return true; } @@ -131,34 +200,23 @@ #endif boost::unique_lock lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked) - { + while(!state.can_lock_shared()) { 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::unique_lock lk(state_change); - bool const last_reader=!--state.shared_count; - if(last_reader) - { - if(state.upgrade) - { - state.upgrade=false; - state.exclusive=true; - upgrade_cond.notify_one(); - } - else - { - state.exclusive_waiting_blocked=false; - } + bool const last_reader = !state.unlock_shared(); + + if (last_reader) { + upgrade_cond.notify_one(); release_waiters(); } } @@ -170,12 +228,12 @@ #endif boost::unique_lock lk(state_change); - while(state.shared_count || state.exclusive) - { - state.exclusive_waiting_blocked=true; + while (!state.can_lock()) { + state.exclusive_blocked(true); exclusive_cond.wait(lk); } - state.exclusive=true; + + state.lock(); } #if defined BOOST_THREAD_USES_DATETIME @@ -186,21 +244,19 @@ #endif boost::unique_lock lk(state_change); - while(state.shared_count || state.exclusive) - { - state.exclusive_waiting_blocked=true; - if(!exclusive_cond.timed_wait(lk,timeout)) - { - if(state.shared_count || state.exclusive) - { - state.exclusive_waiting_blocked=false; + while (!state.can_lock()) { + state.exclusive_blocked(true); + if (!exclusive_cond.timed_wait(lk,timeout)) { + if (!state.can_lock()) { + state.exclusive_blocked(false); release_waiters(); return false; } break; } } - state.exclusive=true; + + state.lock(); return true; } @@ -224,21 +280,19 @@ #endif boost::unique_lock lk(state_change); - while(state.shared_count || state.exclusive) - { - state.exclusive_waiting_blocked=true; - if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time)) - { - if(state.shared_count || state.exclusive) - { - state.exclusive_waiting_blocked=false; + while (!state.can_lock()) { + state.exclusive_blocked(true); + if (cv_status::timeout == exclusive_cond.wait_until(lk,abs_time)) { + if (!state.can_lock()) { + state.exclusive_blocked(false); release_waiters(); return false; } break; } } - state.exclusive=true; + + state.lock(); return true; } #endif @@ -247,23 +301,18 @@ { boost::unique_lock lk(state_change); - if(state.shared_count || state.exclusive) - { + if (!state.can_lock()) return false; - } - else - { - state.exclusive=true; - return true; - } + state.lock(); + return true; } void unlock() { boost::unique_lock lk(state_change); - state.exclusive=false; - state.exclusive_waiting_blocked=false; + + state.unlock(); release_waiters(); } @@ -273,12 +322,11 @@ boost::this_thread::disable_interruption do_not_disturb; #endif boost::unique_lock lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) - { + + while(!state.can_lock_upgrade()) shared_cond.wait(lk); - } - ++state.shared_count; - state.upgrade=true; + + state.lock_upgrade(); } #if defined BOOST_THREAD_USES_DATETIME @@ -288,19 +336,15 @@ boost::this_thread::disable_interruption do_not_disturb; #endif boost::unique_lock lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) - { - if(!shared_cond.timed_wait(lk,timeout)) - { - if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) - { + while (!state.can_lock_upgrade()) { + if (!shared_cond.timed_wait(lk,timeout)) { + if (!state.can_lock_upgrade()) return false; - } + break; } } - ++state.shared_count; - state.upgrade=true; + state.lock_upgrade(); return true; } @@ -323,49 +367,39 @@ boost::this_thread::disable_interruption do_not_disturb; #endif boost::unique_lock lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) - { - if(cv_status::timeout == shared_cond.wait_until(lk,abs_time)) - { - if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) - { + while (!state.can_lock_upgrade()) { + if (cv_status::timeout == shared_cond.wait_until(lk,abs_time)) { + if (!state.can_lock_upgrade()) return false; - } + break; } } - ++state.shared_count; - state.upgrade=true; + state.lock_upgrade(); return true; } #endif bool try_lock_upgrade() { boost::unique_lock lk(state_change); - if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) - { + + if (!state.can_lock_upgrade()) return false; - } - else - { - ++state.shared_count; - state.upgrade=true; - return true; - } + + state.lock_upgrade(); + return true; } void unlock_upgrade() { boost::unique_lock lk(state_change); - state.upgrade=false; - bool const last_reader=!--state.shared_count; - if(last_reader) - { - state.exclusive_waiting_blocked=false; + bool const last_reader = !state.unlock_upgrade(); + + if (last_reader) { release_waiters(); } else { - shared_cond.notify_all(); + shared_cond.notify_all(); } } @@ -376,39 +410,33 @@ boost::this_thread::disable_interruption do_not_disturb; #endif boost::unique_lock lk(state_change); - --state.shared_count; - while(state.shared_count) - { + + state.unlock_upgrade(); + while (!state.can_lock()) upgrade_cond.wait(lk); - } - state.upgrade=false; - state.exclusive=true; + + state.lock(); } void unlock_and_lock_upgrade() { boost::unique_lock lk(state_change); - state.exclusive=false; - state.upgrade=true; - ++state.shared_count; - state.exclusive_waiting_blocked=false; + + state.unlock(); + state.lock_upgrade(); release_waiters(); } bool try_unlock_upgrade_and_lock() { - boost::unique_lock lk(state_change); - if( !state.exclusive - && !state.exclusive_waiting_blocked - && state.upgrade - && state.shared_count==1) - { - state.shared_count=0; - state.exclusive=true; - state.upgrade=false; - return true; - } - return false; + boost::unique_lock lk(state_change); + + if (state.can_lock_shared() && !state.can_lock_upgrade() && state.last_shared()) { + state.unlock_upgrade(); + state.lock(); + return true; + } + return false; } #ifdef BOOST_THREAD_USES_CHRONO template @@ -425,25 +453,22 @@ const chrono::time_point& abs_time) { #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS - boost::this_thread::disable_interruption do_not_disturb; + boost::this_thread::disable_interruption do_not_disturb; #endif - boost::unique_lock lk(state_change); - if (state.shared_count != 1) - { - for (;;) - { - cv_status status = shared_cond.wait_until(lk,abs_time); - if (state.shared_count == 1) - break; - if(status == cv_status::timeout) - return false; - } - } - state.upgrade=false; - state.exclusive=true; - state.exclusive_waiting_blocked=false; - state.shared_count=0; - return true; + boost::unique_lock lk(state_change); + + if (!state.last_shared()) { + for (;;) { + cv_status status = shared_cond.wait_until(lk,abs_time); + if (state.last_shared()) + break; + if (status == cv_status::timeout) + return false; + } + } + state.unlock_upgrade(); + state.lock(); + return true; } #endif @@ -451,26 +476,22 @@ void unlock_and_lock_shared() { boost::unique_lock lk(state_change); - state.exclusive=false; - ++state.shared_count; - state.exclusive_waiting_blocked=false; + + state.unlock(); + state.lock_shared(); release_waiters(); } #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS bool try_unlock_shared_and_lock() { - boost::unique_lock lk(state_change); - if( !state.exclusive - && !state.exclusive_waiting_blocked - && !state.upgrade - && state.shared_count==1) - { - state.shared_count=0; - state.exclusive=true; - return true; - } - return false; + boost::unique_lock lk(state_change); + if (state.can_lock_upgrade() && state.last_shared()) { + state.unlock_shared(); + state.lock(); + return true; + } + return false; } #ifdef BOOST_THREAD_USES_CHRONO template @@ -490,21 +511,17 @@ boost::this_thread::disable_interruption do_not_disturb; #endif boost::unique_lock lk(state_change); - if (state.shared_count != 1) - { - for (;;) - { + if (!state.last_shared()) { + for (;;) { cv_status status = shared_cond.wait_until(lk,abs_time); - if (state.shared_count == 1) - break; + if (state.last_shared()) + break; if(status == cv_status::timeout) - return false; + return false; } } - state.upgrade=false; - state.exclusive=true; - state.exclusive_waiting_blocked=false; - state.shared_count=0; + state.unlock_shared(); + state.lock(); return true; } #endif @@ -514,24 +531,23 @@ void unlock_upgrade_and_lock_shared() { boost::unique_lock lk(state_change); - state.upgrade=false; - state.exclusive_waiting_blocked=false; + + state.unlock_upgrade(); + state.lock_shared(); release_waiters(); } #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS bool try_unlock_shared_and_lock_upgrade() { - boost::unique_lock lk(state_change); - if( !state.exclusive - && !state.exclusive_waiting_blocked - && !state.upgrade - ) - { - state.upgrade=true; - return true; - } - return false; + boost::unique_lock lk(state_change); + + if (state.can_lock_upgrade()) { + state.unlock_shared(); + state.lock_upgrade(); + return true; + } + return false; } #ifdef BOOST_THREAD_USES_CHRONO template @@ -551,24 +567,18 @@ boost::this_thread::disable_interruption do_not_disturb; #endif boost::unique_lock lk(state_change); - if( state.exclusive - || state.exclusive_waiting_blocked - || state.upgrade - ) - { - for (;;) - { + if (!state.can_lock_upgrade()) { + for (;;) { cv_status status = exclusive_cond.wait_until(lk,abs_time); - if( ! state.exclusive - && ! state.exclusive_waiting_blocked - && ! state.upgrade - ) + if(state.can_lock_upgrade()) break; + if(status == cv_status::timeout) return false; } } - state.upgrade=true; + state.unlock_shared(); + state.lock_upgrade(); return true; } #endif