diff options
Diffstat (limited to 'boost/interprocess/sync/interprocess_upgradable_mutex.hpp')
-rw-r--r-- | boost/interprocess/sync/interprocess_upgradable_mutex.hpp | 156 |
1 files changed, 85 insertions, 71 deletions
diff --git a/boost/interprocess/sync/interprocess_upgradable_mutex.hpp b/boost/interprocess/sync/interprocess_upgradable_mutex.hpp index 8d5a452626..b90c71ef7f 100644 --- a/boost/interprocess/sync/interprocess_upgradable_mutex.hpp +++ b/boost/interprocess/sync/interprocess_upgradable_mutex.hpp @@ -1,6 +1,8 @@ -////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// +// Code based on Howard Hinnant's upgrade_mutex class // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,7 +13,7 @@ #ifndef BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP #define BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -195,7 +197,7 @@ class interprocess_upgradable_mutex //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock_upgradable(); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef scoped_lock<interprocess_mutex> scoped_lock_t; @@ -249,7 +251,7 @@ class interprocess_upgradable_mutex if(mp_ctrl){ //Recover upgradable lock mp_ctrl->upgradable_in = 1; - ++mp_ctrl->num_upr_shar; + ++mp_ctrl->num_upr_shar; //Execute the second half of exclusive locking mp_ctrl->exclusive_in = 0; } @@ -264,10 +266,10 @@ class interprocess_upgradable_mutex = ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2)); }; typedef base_constants_t<0> constants; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) template <int Dummy> const unsigned interprocess_upgradable_mutex::base_constants_t<Dummy>::max_readers; @@ -284,12 +286,12 @@ inline interprocess_upgradable_mutex::~interprocess_upgradable_mutex() inline void interprocess_upgradable_mutex::lock() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //The exclusive lock must block in the first gate //if an exclusive or upgradable lock has been acquired while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ - this->m_first_gate.wait(lock); + this->m_first_gate.wait(lck); } //Mark that exclusive lock has been acquired @@ -300,18 +302,18 @@ inline void interprocess_upgradable_mutex::lock() //Now wait until all readers are gone while (this->m_ctrl.num_upr_shar){ - this->m_second_gate.wait(lock); + this->m_second_gate.wait(lck); } rollback.release(); } inline bool interprocess_upgradable_mutex::try_lock() { - scoped_lock_t lock(m_mut, try_to_lock); + scoped_lock_t lck(m_mut, try_to_lock); //If we can't lock or any has there is any exclusive, upgradable //or sharable mark return false; - if(!lock.owns() + if(!lck.owns() || this->m_ctrl.exclusive_in || this->m_ctrl.num_upr_shar){ return false; @@ -323,18 +325,20 @@ inline bool interprocess_upgradable_mutex::try_lock() inline bool interprocess_upgradable_mutex::timed_lock (const boost::posix_time::ptime &abs_time) { - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - scoped_lock_t lock(m_mut, abs_time); - if(!lock.owns()) return false; + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; //The exclusive lock must block in the first gate //if an exclusive or upgradable lock has been acquired while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ - if(!this->m_first_gate.timed_wait(lock, abs_time)) - return !(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in); + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ + return false; + } + break; + } } //Mark that exclusive lock has been acquired @@ -345,8 +349,11 @@ inline bool interprocess_upgradable_mutex::timed_lock //Now wait until all readers are gone while (this->m_ctrl.num_upr_shar){ - if(!this->m_second_gate.timed_wait(lock, abs_time)){ - return !(this->m_ctrl.num_upr_shar); + if(!this->m_second_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.num_upr_shar){ + return false; + } + break; } } rollback.release(); @@ -355,7 +362,7 @@ inline bool interprocess_upgradable_mutex::timed_lock inline void interprocess_upgradable_mutex::unlock() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); this->m_ctrl.exclusive_in = 0; this->m_first_gate.notify_all(); } @@ -364,14 +371,14 @@ inline void interprocess_upgradable_mutex::unlock() inline void interprocess_upgradable_mutex::lock_upgradable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //The upgradable lock must block in the first gate //if an exclusive or upgradable lock has been acquired //or there are too many sharable locks while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar == constants::max_readers){ - this->m_first_gate.wait(lock); + this->m_first_gate.wait(lck); } //Mark that upgradable lock has been acquired @@ -382,12 +389,12 @@ inline void interprocess_upgradable_mutex::lock_upgradable() inline bool interprocess_upgradable_mutex::try_lock_upgradable() { - scoped_lock_t lock(m_mut, try_to_lock); + scoped_lock_t lck(m_mut, try_to_lock); //The upgradable lock must fail //if an exclusive or upgradable lock has been acquired //or there are too many sharable locks - if(!lock.owns() + if(!lck.owns() || this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar == constants::max_readers){ @@ -404,12 +411,10 @@ inline bool interprocess_upgradable_mutex::try_lock_upgradable() inline bool interprocess_upgradable_mutex::timed_lock_upgradable (const boost::posix_time::ptime &abs_time) { - if(abs_time == boost::posix_time::pos_infin){ - this->lock_upgradable(); - return true; - } - scoped_lock_t lock(m_mut, abs_time); - if(!lock.owns()) return false; + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; //The upgradable lock must block in the first gate //if an exclusive or upgradable lock has been acquired @@ -417,10 +422,13 @@ inline bool interprocess_upgradable_mutex::timed_lock_upgradable while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar == constants::max_readers){ - if(!this->m_first_gate.timed_wait(lock, abs_time)){ - return!(this->m_ctrl.exclusive_in - || this->m_ctrl.upgradable_in - || this->m_ctrl.num_upr_shar == constants::max_readers); + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if((this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar == constants::max_readers)){ + return false; + } + break; } } @@ -433,7 +441,7 @@ inline bool interprocess_upgradable_mutex::timed_lock_upgradable inline void interprocess_upgradable_mutex::unlock_upgradable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //Mark that upgradable lock has been acquired //And add upgradable to the sharable count this->m_ctrl.upgradable_in = 0; @@ -445,14 +453,14 @@ inline void interprocess_upgradable_mutex::unlock_upgradable() inline void interprocess_upgradable_mutex::lock_sharable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //The sharable lock must block in the first gate //if an exclusive lock has been acquired //or there are too many sharable locks while(this->m_ctrl.exclusive_in || this->m_ctrl.num_upr_shar == constants::max_readers){ - this->m_first_gate.wait(lock); + this->m_first_gate.wait(lck); } //Increment sharable count @@ -461,12 +469,12 @@ inline void interprocess_upgradable_mutex::lock_sharable() inline bool interprocess_upgradable_mutex::try_lock_sharable() { - scoped_lock_t lock(m_mut, try_to_lock); + scoped_lock_t lck(m_mut, try_to_lock); //The sharable lock must fail //if an exclusive lock has been acquired //or there are too many sharable locks - if(!lock.owns() + if(!lck.owns() || this->m_ctrl.exclusive_in || this->m_ctrl.num_upr_shar == constants::max_readers){ return false; @@ -480,21 +488,22 @@ inline bool interprocess_upgradable_mutex::try_lock_sharable() inline bool interprocess_upgradable_mutex::timed_lock_sharable (const boost::posix_time::ptime &abs_time) { - if(abs_time == boost::posix_time::pos_infin){ - this->lock_sharable(); - return true; - } - scoped_lock_t lock(m_mut, abs_time); - if(!lock.owns()) return false; + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; //The sharable lock must block in the first gate //if an exclusive lock has been acquired //or there are too many sharable locks while (this->m_ctrl.exclusive_in || this->m_ctrl.num_upr_shar == constants::max_readers){ - if(!this->m_first_gate.timed_wait(lock, abs_time)){ - return!(this->m_ctrl.exclusive_in - || this->m_ctrl.num_upr_shar == constants::max_readers); + if(!this->m_first_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + return false; + } + break; } } @@ -505,7 +514,7 @@ inline bool interprocess_upgradable_mutex::timed_lock_sharable inline void interprocess_upgradable_mutex::unlock_sharable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //Decrement sharable count --this->m_ctrl.num_upr_shar; if (this->m_ctrl.num_upr_shar == 0){ @@ -522,7 +531,7 @@ inline void interprocess_upgradable_mutex::unlock_sharable() inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //Unmark it as exclusive this->m_ctrl.exclusive_in = 0; //Mark it as upgradable @@ -535,7 +544,7 @@ inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable() inline void interprocess_upgradable_mutex::unlock_and_lock_sharable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //Unmark it as exclusive this->m_ctrl.exclusive_in = 0; //The sharable count should be 0 so increment it @@ -546,7 +555,7 @@ inline void interprocess_upgradable_mutex::unlock_and_lock_sharable() inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //Unmark it as upgradable (we don't have to decrement count) this->m_ctrl.upgradable_in = 0; //Notify readers/upgradable that they can enter @@ -557,11 +566,11 @@ inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable() inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock() { - scoped_lock_t lock(m_mut); + scoped_lock_t lck(m_mut); //Simulate unlock_upgradable() without //notifying sharables. this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; + --this->m_ctrl.num_upr_shar; //Execute the second half of exclusive locking this->m_ctrl.exclusive_in = 1; @@ -569,22 +578,22 @@ inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock() upgradable_to_exclusive_rollback rollback(m_ctrl); while (this->m_ctrl.num_upr_shar){ - this->m_second_gate.wait(lock); + this->m_second_gate.wait(lck); } rollback.release(); } inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock() { - scoped_lock_t lock(m_mut, try_to_lock); + scoped_lock_t lck(m_mut, try_to_lock); //Check if there are no readers - if(!lock.owns() + if(!lck.owns() || this->m_ctrl.num_upr_shar != 1){ return false; } //Now unlock upgradable and mark exclusive this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; + --this->m_ctrl.num_upr_shar; this->m_ctrl.exclusive_in = 1; return true; } @@ -592,13 +601,15 @@ inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock() inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock (const boost::posix_time::ptime &abs_time) { - scoped_lock_t lock(m_mut, abs_time); - if(!lock.owns()) return false; + //Mutexes and condvars handle just fine infinite abs_times + //so avoid checking it here + scoped_lock_t lck(m_mut, abs_time); + if(!lck.owns()) return false; //Simulate unlock_upgradable() without //notifying sharables. this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; + --this->m_ctrl.num_upr_shar; //Execute the second half of exclusive locking this->m_ctrl.exclusive_in = 1; @@ -606,8 +617,11 @@ inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock upgradable_to_exclusive_rollback rollback(m_ctrl); while (this->m_ctrl.num_upr_shar){ - if(!this->m_second_gate.timed_wait(lock, abs_time)){ - return !(this->m_ctrl.num_upr_shar); + if(!this->m_second_gate.timed_wait(lck, abs_time)){ + if(this->m_ctrl.num_upr_shar){ + return false; + } + break; } } rollback.release(); @@ -616,11 +630,11 @@ inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock() { - scoped_lock_t lock(m_mut, try_to_lock); + scoped_lock_t lck(m_mut, try_to_lock); //If we can't lock or any has there is any exclusive, upgradable //or sharable mark return false; - if(!lock.owns() + if(!lck.owns() || this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar != 1){ @@ -633,11 +647,11 @@ inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock() inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() { - scoped_lock_t lock(m_mut, try_to_lock); + scoped_lock_t lck(m_mut, try_to_lock); //The upgradable lock must fail //if an exclusive or upgradable lock has been acquired - if(!lock.owns() + if(!lck.owns() || this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ return false; @@ -648,7 +662,7 @@ inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradab return true; } -/// @endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { |