Index: boost/thread/pthread/shared_mutex.hpp =================================================================== --- boost/thread/pthread/shared_mutex.hpp (revision 82382) +++ boost/thread/pthread/shared_mutex.hpp (working copy) @@ -30,16 +30,66 @@ private: struct state_data { + 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; + } + + 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; + } + 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 +105,6 @@ shared_mutex() { - state_data state_={0,0,0,0}; - state=state_; } ~shared_mutex() @@ -70,26 +118,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 +143,13 @@ #endif boost::unique_lock lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked) + while(!state.can_lock_shared()) { - if(!shared_cond.timed_wait(lk,timeout)) - { + if (!shared_cond.timed_wait(lk,timeout)) return false; - } } - ++state.shared_count; + + state.lock_shared(); return true; } @@ -131,34 +173,28 @@ #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) + bool upgrade = state.upgrade; + bool const last_reader = !state.unlock_shared(); + + if (last_reader) { - if(state.upgrade) - { - state.upgrade=false; - state.exclusive=true; + if (upgrade) upgrade_cond.notify_one(); - } - else - { - state.exclusive_waiting_blocked=false; - } + release_waiters(); } } @@ -170,12 +206,13 @@ #endif boost::unique_lock lk(state_change); - while(state.shared_count || state.exclusive) + while(!state.can_lock()) { - state.exclusive_waiting_blocked=true; + state.exclusive_blocked(true); exclusive_cond.wait(lk); } - state.exclusive=true; + + state.lock(); } #if defined BOOST_THREAD_USES_DATETIME @@ -186,21 +223,22 @@ #endif boost::unique_lock lk(state_change); - while(state.shared_count || state.exclusive) + while (!state.can_lock()) { - state.exclusive_waiting_blocked=true; - if(!exclusive_cond.timed_wait(lk,timeout)) + state.exclusive_blocked(true); + if (!exclusive_cond.timed_wait(lk,timeout)) { - if(state.shared_count || state.exclusive) + if (!state.can_lock()) { - state.exclusive_waiting_blocked=false; + state.exclusive_blocked(false); release_waiters(); return false; } break; } } - state.exclusive=true; + + state.lock(); return true; } @@ -224,21 +262,22 @@ #endif boost::unique_lock lk(state_change); - while(state.shared_count || state.exclusive) + while (!state.can_lock()) { - state.exclusive_waiting_blocked=true; + state.exclusive_blocked(true); if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time)) { - if(state.shared_count || state.exclusive) + if (!state.can_lock()) { - state.exclusive_waiting_blocked=false; + state.exclusive_blocked(false); release_waiters(); return false; } break; } } - state.exclusive=true; + + state.lock(); return true; } #endif @@ -247,23 +286,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(); }