EVOLUTION-MANAGER
Edit File: condition_any_algorithm.hpp
////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2012-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) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP #define BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP #ifndef BOOST_CONFIG_HPP # include <boost/config.hpp> #endif # #if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> #include <boost/interprocess/sync/detail/locks.hpp> #include <limits> namespace boost { namespace interprocess { namespace ipcdetail { //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // // Condition variable 'any' (able to use any type of external mutex) // // The code is based on Howard E. Hinnant's ISO C++ N2406 paper. // Many thanks to Howard for his support and comments. //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Required interface for ConditionAnyMembers // class ConditionAnyMembers // { // typedef implementation_defined mutex_type; // typedef implementation_defined condvar_type; // // condvar &get_condvar() // mutex_type &get_mutex() // }; // // Must be initialized as following // // get_condvar() [no threads blocked] // get_mutex() [unlocked] template<class ConditionAnyMembers> class condition_any_algorithm { private: condition_any_algorithm(); ~condition_any_algorithm(); condition_any_algorithm(const condition_any_algorithm &); condition_any_algorithm &operator=(const condition_any_algorithm &); typedef typename ConditionAnyMembers::mutex_type mutex_type; typedef typename ConditionAnyMembers::condvar_type condvar_type; template <class Lock> static void do_wait(ConditionAnyMembers &data, Lock& lock); template <class Lock> static bool do_timed_wait(ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time); public: template<class Lock> static bool wait ( ConditionAnyMembers &data, Lock &mut , bool timeout_enabled, const boost::posix_time::ptime &abs_time); static void signal( ConditionAnyMembers &data, bool broadcast); }; template<class ConditionAnyMembers> void condition_any_algorithm<ConditionAnyMembers>::signal(ConditionAnyMembers &data, bool broadcast) { scoped_lock<mutex_type> internal_lock(data.get_mutex()); if(broadcast){ data.get_condvar().notify_all(); } else{ data.get_condvar().notify_one(); } } template<class ConditionAnyMembers> template<class Lock> bool condition_any_algorithm<ConditionAnyMembers>::wait ( ConditionAnyMembers &data , Lock &lock , bool tout_enabled , const boost::posix_time::ptime &abs_time) { if(tout_enabled){ return condition_any_algorithm::do_timed_wait(data, lock, abs_time); } else{ condition_any_algorithm::do_wait(data, lock); return true; } } template<class ConditionAnyMembers> template <class Lock> void condition_any_algorithm<ConditionAnyMembers>::do_wait (ConditionAnyMembers &data, Lock& lock) { //lock internal before unlocking external to avoid race with a notifier scoped_lock<mutex_type> internal_lock(data.get_mutex()); { lock_inverter<Lock> inverted_lock(lock); scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock); { //unlock internal first to avoid deadlock with near simultaneous waits scoped_lock<mutex_type> internal_unlock; internal_lock.swap(internal_unlock); data.get_condvar().wait(internal_unlock); } } } template<class ConditionAnyMembers> template <class Lock> bool condition_any_algorithm<ConditionAnyMembers>::do_timed_wait (ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time) { //lock internal before unlocking external to avoid race with a notifier scoped_lock<mutex_type> internal_lock(data.get_mutex()); { //Unlock external lock and program for relock lock_inverter<Lock> inverted_lock(lock); scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock); { //unlock internal first to avoid deadlock with near simultaneous waits scoped_lock<mutex_type> internal_unlock; internal_lock.swap(internal_unlock); return data.get_condvar().timed_wait(internal_unlock, abs_time); } } } template<class ConditionAnyMembers> class condition_any_wrapper { //Non-copyable condition_any_wrapper(const condition_any_wrapper &); condition_any_wrapper &operator=(const condition_any_wrapper &); ConditionAnyMembers m_data; typedef ipcdetail::condition_any_algorithm<ConditionAnyMembers> algo_type; public: condition_any_wrapper(){} ~condition_any_wrapper(){} ConditionAnyMembers & get_members() { return m_data; } const ConditionAnyMembers & get_members() const { return m_data; } void notify_one() { algo_type::signal(m_data, false); } void notify_all() { algo_type::signal(m_data, true); } template <typename L> void wait(L& lock) { if (!lock) throw lock_exception(); algo_type::wait(m_data, lock, false, boost::posix_time::ptime()); } template <typename L, typename Pr> void wait(L& lock, Pr pred) { if (!lock) throw lock_exception(); while (!pred()) algo_type::wait(m_data, lock, false, boost::posix_time::ptime()); } template <typename L> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) { if (!lock) throw lock_exception(); return algo_type::wait(m_data, lock, true, abs_time); } template <typename L, typename Pr> bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) { if (!lock) throw lock_exception(); while (!pred()){ if (!algo_type::wait(m_data, lock, true, abs_time)) return pred(); } return true; } }; } //namespace ipcdetail } //namespace interprocess } //namespace boost #include <boost/interprocess/detail/config_end.hpp> #endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP