]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/thread/pthread/condition_variable_fwd.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / thread / pthread / condition_variable_fwd.hpp
1 #ifndef BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
2 #define BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 // (C) Copyright 2007-8 Anthony Williams
7 // (C) Copyright 2011-2012 Vicente J. Botet Escriba
8
9 #include <boost/assert.hpp>
10 #include <boost/throw_exception.hpp>
11 #include <pthread.h>
12 #include <boost/thread/cv_status.hpp>
13 #include <boost/thread/mutex.hpp>
14 #include <boost/thread/lock_types.hpp>
15 #include <boost/thread/thread_time.hpp>
16 #include <boost/thread/pthread/timespec.hpp>
17 #if defined BOOST_THREAD_USES_DATETIME
18 #include <boost/thread/xtime.hpp>
19 #endif
20
21 #ifdef BOOST_THREAD_USES_CHRONO
22 #include <boost/chrono/system_clocks.hpp>
23 #include <boost/chrono/ceil.hpp>
24 #endif
25 #include <boost/thread/detail/delete.hpp>
26 #include <boost/date_time/posix_time/posix_time_duration.hpp>
27
28 #include <boost/config/abi_prefix.hpp>
29
30 namespace boost
31 {
32 namespace detail {
33 inline int monotonic_pthread_cond_init(pthread_cond_t& cond) {
34
35 #ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
36 pthread_condattr_t attr;
37 int res = pthread_condattr_init(&attr);
38 if (res)
39 {
40 return res;
41 }
42 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
43 res=pthread_cond_init(&cond,&attr);
44 pthread_condattr_destroy(&attr);
45 return res;
46 #else
47 return pthread_cond_init(&cond,NULL);
48 #endif
49
50 }
51 }
52
53 class condition_variable
54 {
55 private:
56 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
57 pthread_mutex_t internal_mutex;
58 //#endif
59 pthread_cond_t cond;
60
61 public:
62 //private: // used by boost::thread::try_join_until
63
64 inline bool do_wait_until(
65 unique_lock<mutex>& lock,
66 struct timespec const &timeout);
67
68 bool do_wait_for(
69 unique_lock<mutex>& lock,
70 struct timespec const &timeout)
71 {
72 #if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
73 return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_monotonic()));
74 #else
75 // old behavior was fine for monotonic
76 return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_realtime()));
77 #endif
78 }
79
80 public:
81 BOOST_THREAD_NO_COPYABLE(condition_variable)
82 condition_variable()
83 {
84 int res;
85 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
86 // Even if it is not used, the internal_mutex exists (see
87 // above) and must be initialized (etc) in case some
88 // compilation units provide interruptions and others
89 // don't.
90 res=pthread_mutex_init(&internal_mutex,NULL);
91 if(res)
92 {
93 boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
94 }
95 //#endif
96 res = detail::monotonic_pthread_cond_init(cond);
97 if (res)
98 {
99 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
100 // ditto
101 BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
102 //#endif
103 boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init"));
104 }
105 }
106 ~condition_variable()
107 {
108 int ret;
109 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
110 // ditto
111 do {
112 ret = pthread_mutex_destroy(&internal_mutex);
113 } while (ret == EINTR);
114 BOOST_ASSERT(!ret);
115 //#endif
116 do {
117 ret = pthread_cond_destroy(&cond);
118 } while (ret == EINTR);
119 BOOST_ASSERT(!ret);
120 }
121
122 void wait(unique_lock<mutex>& m);
123
124 template<typename predicate_type>
125 void wait(unique_lock<mutex>& m,predicate_type pred)
126 {
127 while(!pred()) wait(m);
128 }
129
130 #if defined BOOST_THREAD_USES_DATETIME
131 inline bool timed_wait(
132 unique_lock<mutex>& m,
133 boost::system_time const& abs_time)
134 {
135 #if defined BOOST_THREAD_WAIT_BUG
136 struct timespec const timeout=detail::to_timespec(abs_time + BOOST_THREAD_WAIT_BUG);
137 return do_wait_until(m, timeout);
138 #else
139 struct timespec const timeout=detail::to_timespec(abs_time);
140 return do_wait_until(m, timeout);
141 #endif
142 }
143 bool timed_wait(
144 unique_lock<mutex>& m,
145 xtime const& abs_time)
146 {
147 return timed_wait(m,system_time(abs_time));
148 }
149
150 template<typename duration_type>
151 bool timed_wait(
152 unique_lock<mutex>& m,
153 duration_type const& wait_duration)
154 {
155 if (wait_duration.is_pos_infinity())
156 {
157 wait(m); // or do_wait(m,detail::timeout::sentinel());
158 return true;
159 }
160 if (wait_duration.is_special())
161 {
162 return true;
163 }
164 return timed_wait(m,get_system_time()+wait_duration);
165 }
166
167 template<typename predicate_type>
168 bool timed_wait(
169 unique_lock<mutex>& m,
170 boost::system_time const& abs_time,predicate_type pred)
171 {
172 while (!pred())
173 {
174 if(!timed_wait(m, abs_time))
175 return pred();
176 }
177 return true;
178 }
179
180 template<typename predicate_type>
181 bool timed_wait(
182 unique_lock<mutex>& m,
183 xtime const& abs_time,predicate_type pred)
184 {
185 return timed_wait(m,system_time(abs_time),pred);
186 }
187
188 template<typename duration_type,typename predicate_type>
189 bool timed_wait(
190 unique_lock<mutex>& m,
191 duration_type const& wait_duration,predicate_type pred)
192 {
193 if (wait_duration.is_pos_infinity())
194 {
195 while (!pred())
196 {
197 wait(m); // or do_wait(m,detail::timeout::sentinel());
198 }
199 return true;
200 }
201 if (wait_duration.is_special())
202 {
203 return pred();
204 }
205 return timed_wait(m,get_system_time()+wait_duration,pred);
206 }
207 #endif
208
209 #ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
210
211 #ifdef BOOST_THREAD_USES_CHRONO
212
213 template <class Duration>
214 cv_status
215 wait_until(
216 unique_lock<mutex>& lock,
217 const chrono::time_point<chrono::system_clock, Duration>& t)
218 {
219 using namespace chrono;
220 typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
221 wait_until(lock,
222 nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
223 return system_clock::now() < t ? cv_status::no_timeout :
224 cv_status::timeout;
225 }
226
227 template <class Clock, class Duration>
228 cv_status
229 wait_until(
230 unique_lock<mutex>& lock,
231 const chrono::time_point<Clock, Duration>& t)
232 {
233 using namespace chrono;
234 system_clock::time_point s_now = system_clock::now();
235 typename Clock::time_point c_now = Clock::now();
236 wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
237 return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
238 }
239
240
241
242 template <class Rep, class Period>
243 cv_status
244 wait_for(
245 unique_lock<mutex>& lock,
246 const chrono::duration<Rep, Period>& d)
247 {
248 using namespace chrono;
249 system_clock::time_point s_now = system_clock::now();
250 steady_clock::time_point c_now = steady_clock::now();
251 wait_until(lock, s_now + ceil<nanoseconds>(d));
252 return steady_clock::now() - c_now < d ? cv_status::no_timeout :
253 cv_status::timeout;
254
255 }
256
257 inline cv_status wait_until(
258 unique_lock<mutex>& lk,
259 chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
260 {
261 using namespace chrono;
262 nanoseconds d = tp.time_since_epoch();
263 timespec ts = boost::detail::to_timespec(d);
264 if (do_wait_until(lk, ts)) return cv_status::no_timeout;
265 else return cv_status::timeout;
266 }
267 #endif
268
269 #else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
270 #ifdef BOOST_THREAD_USES_CHRONO
271
272 template <class Duration>
273 cv_status
274 wait_until(
275 unique_lock<mutex>& lock,
276 const chrono::time_point<chrono::steady_clock, Duration>& t)
277 {
278 using namespace chrono;
279 typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
280 wait_until(lock,
281 nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
282 return steady_clock::now() < t ? cv_status::no_timeout :
283 cv_status::timeout;
284 }
285
286 template <class Clock, class Duration>
287 cv_status
288 wait_until(
289 unique_lock<mutex>& lock,
290 const chrono::time_point<Clock, Duration>& t)
291 {
292 using namespace chrono;
293 steady_clock::time_point s_now = steady_clock::now();
294 typename Clock::time_point c_now = Clock::now();
295 wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
296 return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
297 }
298
299 template <class Rep, class Period>
300 cv_status
301 wait_for(
302 unique_lock<mutex>& lock,
303 const chrono::duration<Rep, Period>& d)
304 {
305 using namespace chrono;
306 steady_clock::time_point c_now = steady_clock::now();
307 wait_until(lock, c_now + ceil<nanoseconds>(d));
308 return steady_clock::now() - c_now < d ? cv_status::no_timeout :
309 cv_status::timeout;
310 }
311
312 inline cv_status wait_until(
313 unique_lock<mutex>& lk,
314 chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
315 {
316 using namespace chrono;
317 nanoseconds d = tp.time_since_epoch();
318 timespec ts = boost::detail::to_timespec(d);
319 if (do_wait_until(lk, ts)) return cv_status::no_timeout;
320 else return cv_status::timeout;
321 }
322 #endif
323
324 #endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
325
326 #ifdef BOOST_THREAD_USES_CHRONO
327 template <class Clock, class Duration, class Predicate>
328 bool
329 wait_until(
330 unique_lock<mutex>& lock,
331 const chrono::time_point<Clock, Duration>& t,
332 Predicate pred)
333 {
334 while (!pred())
335 {
336 if (wait_until(lock, t) == cv_status::timeout)
337 return pred();
338 }
339 return true;
340 }
341
342 template <class Rep, class Period, class Predicate>
343 bool
344 wait_for(
345 unique_lock<mutex>& lock,
346 const chrono::duration<Rep, Period>& d,
347 Predicate pred)
348 {
349 return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
350 }
351 #endif
352
353 #define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE
354 typedef pthread_cond_t* native_handle_type;
355 native_handle_type native_handle()
356 {
357 return &cond;
358 }
359
360 void notify_one() BOOST_NOEXCEPT;
361 void notify_all() BOOST_NOEXCEPT;
362
363
364 };
365
366 BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
367
368 }
369
370
371 #include <boost/config/abi_suffix.hpp>
372
373 #endif