1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // See http://www.boost.org/libs/interprocess for documentation.
9 //////////////////////////////////////////////////////////////////////////////
11 #ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
12 #define BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
14 #ifndef BOOST_CONFIG_HPP
15 # include <boost/config.hpp>
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
22 #include <boost/interprocess/detail/config_begin.hpp>
23 #include <boost/interprocess/detail/workaround.hpp>
24 #include <boost/interprocess/sync/scoped_lock.hpp>
25 #include <boost/interprocess/sync/detail/locks.hpp>
29 namespace interprocess {
32 ////////////////////////////////////////////////////////////////////////
33 ////////////////////////////////////////////////////////////////////////
34 ////////////////////////////////////////////////////////////////////////
36 // Condition variable 'any' (able to use any type of external mutex)
38 // The code is based on Howard E. Hinnant's ISO C++ N2406 paper.
39 // Many thanks to Howard for his support and comments.
40 ////////////////////////////////////////////////////////////////////////
41 ////////////////////////////////////////////////////////////////////////
42 ////////////////////////////////////////////////////////////////////////
44 // Required interface for ConditionAnyMembers
45 // class ConditionAnyMembers
47 // typedef implementation_defined mutex_type;
48 // typedef implementation_defined condvar_type;
50 // condvar &get_condvar()
51 // mutex_type &get_mutex()
54 // Must be initialized as following
56 // get_condvar() [no threads blocked]
57 // get_mutex() [unlocked]
59 template<class ConditionAnyMembers>
60 class condition_any_algorithm
63 condition_any_algorithm();
64 ~condition_any_algorithm();
65 condition_any_algorithm(const condition_any_algorithm &);
66 condition_any_algorithm &operator=(const condition_any_algorithm &);
68 typedef typename ConditionAnyMembers::mutex_type mutex_type;
69 typedef typename ConditionAnyMembers::condvar_type condvar_type;
72 static void do_wait(ConditionAnyMembers &data, Lock& lock);
75 static bool do_timed_wait(ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time);
79 static bool wait ( ConditionAnyMembers &data, Lock &mut
80 , bool timeout_enabled, const boost::posix_time::ptime &abs_time);
81 static void signal( ConditionAnyMembers &data, bool broadcast);
84 template<class ConditionAnyMembers>
85 void condition_any_algorithm<ConditionAnyMembers>::signal(ConditionAnyMembers &data, bool broadcast)
87 scoped_lock<mutex_type> internal_lock(data.get_mutex());
89 data.get_condvar().notify_all();
92 data.get_condvar().notify_one();
96 template<class ConditionAnyMembers>
98 bool condition_any_algorithm<ConditionAnyMembers>::wait
99 ( ConditionAnyMembers &data
102 , const boost::posix_time::ptime &abs_time)
105 return condition_any_algorithm::do_timed_wait(data, lock, abs_time);
108 condition_any_algorithm::do_wait(data, lock);
113 template<class ConditionAnyMembers>
114 template <class Lock>
115 void condition_any_algorithm<ConditionAnyMembers>::do_wait
116 (ConditionAnyMembers &data, Lock& lock)
118 //lock internal before unlocking external to avoid race with a notifier
119 scoped_lock<mutex_type> internal_lock(data.get_mutex());
121 lock_inverter<Lock> inverted_lock(lock);
122 scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
123 { //unlock internal first to avoid deadlock with near simultaneous waits
124 scoped_lock<mutex_type> internal_unlock;
125 internal_lock.swap(internal_unlock);
126 data.get_condvar().wait(internal_unlock);
131 template<class ConditionAnyMembers>
132 template <class Lock>
133 bool condition_any_algorithm<ConditionAnyMembers>::do_timed_wait
134 (ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time)
136 //lock internal before unlocking external to avoid race with a notifier
137 scoped_lock<mutex_type> internal_lock(data.get_mutex());
139 //Unlock external lock and program for relock
140 lock_inverter<Lock> inverted_lock(lock);
141 scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
142 { //unlock internal first to avoid deadlock with near simultaneous waits
143 scoped_lock<mutex_type> internal_unlock;
144 internal_lock.swap(internal_unlock);
145 return data.get_condvar().timed_wait(internal_unlock, abs_time);
151 template<class ConditionAnyMembers>
152 class condition_any_wrapper
155 condition_any_wrapper(const condition_any_wrapper &);
156 condition_any_wrapper &operator=(const condition_any_wrapper &);
158 ConditionAnyMembers m_data;
159 typedef ipcdetail::condition_any_algorithm<ConditionAnyMembers> algo_type;
163 condition_any_wrapper(){}
165 ~condition_any_wrapper(){}
167 ConditionAnyMembers & get_members()
170 const ConditionAnyMembers & get_members() const
174 { algo_type::signal(m_data, false); }
177 { algo_type::signal(m_data, true); }
179 template <typename L>
183 throw lock_exception();
184 algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
187 template <typename L, typename Pr>
188 void wait(L& lock, Pr pred)
191 throw lock_exception();
194 algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
197 template <typename L>
198 bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
201 throw lock_exception();
202 return algo_type::wait(m_data, lock, true, abs_time);
205 template <typename L, typename Pr>
206 bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
209 throw lock_exception();
211 if (!algo_type::wait(m_data, lock, true, abs_time))
218 } //namespace ipcdetail
219 } //namespace interprocess
222 #include <boost/interprocess/detail/config_end.hpp>
224 #endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP