]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/interprocess/sync/detail/condition_any_algorithm.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / interprocess / sync / detail / condition_any_algorithm.hpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
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)
6 //
7 // See http://www.boost.org/libs/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10
11 #ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
12 #define BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
13
14 #ifndef BOOST_CONFIG_HPP
15 # include <boost/config.hpp>
16 #endif
17 #
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 # pragma once
20 #endif
21
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>
26 #include <limits>
27
28 namespace boost {
29 namespace interprocess {
30 namespace ipcdetail {
31
32 ////////////////////////////////////////////////////////////////////////
33 ////////////////////////////////////////////////////////////////////////
34 ////////////////////////////////////////////////////////////////////////
35 //
36 // Condition variable 'any' (able to use any type of external mutex)
37 //
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 ////////////////////////////////////////////////////////////////////////
43
44 // Required interface for ConditionAnyMembers
45 // class ConditionAnyMembers
46 // {
47 // typedef implementation_defined mutex_type;
48 // typedef implementation_defined condvar_type;
49 //
50 // condvar &get_condvar()
51 // mutex_type &get_mutex()
52 // };
53 //
54 // Must be initialized as following
55 //
56 // get_condvar() [no threads blocked]
57 // get_mutex() [unlocked]
58
59 template<class ConditionAnyMembers>
60 class condition_any_algorithm
61 {
62 private:
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 &);
67
68 typedef typename ConditionAnyMembers::mutex_type mutex_type;
69 typedef typename ConditionAnyMembers::condvar_type condvar_type;
70
71 template <class Lock>
72 static void do_wait(ConditionAnyMembers &data, Lock& lock);
73
74 template <class Lock>
75 static bool do_timed_wait(ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time);
76
77 public:
78 template<class Lock>
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);
82 };
83
84 template<class ConditionAnyMembers>
85 void condition_any_algorithm<ConditionAnyMembers>::signal(ConditionAnyMembers &data, bool broadcast)
86 {
87 scoped_lock<mutex_type> internal_lock(data.get_mutex());
88 if(broadcast){
89 data.get_condvar().notify_all();
90 }
91 else{
92 data.get_condvar().notify_one();
93 }
94 }
95
96 template<class ConditionAnyMembers>
97 template<class Lock>
98 bool condition_any_algorithm<ConditionAnyMembers>::wait
99 ( ConditionAnyMembers &data
100 , Lock &lock
101 , bool tout_enabled
102 , const boost::posix_time::ptime &abs_time)
103 {
104 if(tout_enabled){
105 return condition_any_algorithm::do_timed_wait(data, lock, abs_time);
106 }
107 else{
108 condition_any_algorithm::do_wait(data, lock);
109 return true;
110 }
111 }
112
113 template<class ConditionAnyMembers>
114 template <class Lock>
115 void condition_any_algorithm<ConditionAnyMembers>::do_wait
116 (ConditionAnyMembers &data, Lock& lock)
117 {
118 //lock internal before unlocking external to avoid race with a notifier
119 scoped_lock<mutex_type> internal_lock(data.get_mutex());
120 {
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);
127 }
128 }
129 }
130
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)
135 {
136 //lock internal before unlocking external to avoid race with a notifier
137 scoped_lock<mutex_type> internal_lock(data.get_mutex());
138 {
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);
146 }
147 }
148 }
149
150
151 template<class ConditionAnyMembers>
152 class condition_any_wrapper
153 {
154 //Non-copyable
155 condition_any_wrapper(const condition_any_wrapper &);
156 condition_any_wrapper &operator=(const condition_any_wrapper &);
157
158 ConditionAnyMembers m_data;
159 typedef ipcdetail::condition_any_algorithm<ConditionAnyMembers> algo_type;
160
161 public:
162
163 condition_any_wrapper(){}
164
165 ~condition_any_wrapper(){}
166
167 ConditionAnyMembers & get_members()
168 { return m_data; }
169
170 const ConditionAnyMembers & get_members() const
171 { return m_data; }
172
173 void notify_one()
174 { algo_type::signal(m_data, false); }
175
176 void notify_all()
177 { algo_type::signal(m_data, true); }
178
179 template <typename L>
180 void wait(L& lock)
181 {
182 if (!lock)
183 throw lock_exception();
184 algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
185 }
186
187 template <typename L, typename Pr>
188 void wait(L& lock, Pr pred)
189 {
190 if (!lock)
191 throw lock_exception();
192
193 while (!pred())
194 algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
195 }
196
197 template <typename L>
198 bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
199 {
200 if (!lock)
201 throw lock_exception();
202 return algo_type::wait(m_data, lock, true, abs_time);
203 }
204
205 template <typename L, typename Pr>
206 bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
207 {
208 if (!lock)
209 throw lock_exception();
210 while (!pred()){
211 if (!algo_type::wait(m_data, lock, true, abs_time))
212 return pred();
213 }
214 return true;
215 }
216 };
217
218 } //namespace ipcdetail
219 } //namespace interprocess
220 } //namespace boost
221
222 #include <boost/interprocess/detail/config_end.hpp>
223
224 #endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP