]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/thread/pthread/condition_variable_fwd.hpp
update source to Ceph Pacific 16.2.2
[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/detail/platform_time.hpp>
17 #include <boost/thread/pthread/pthread_helpers.hpp>
18
19 #if defined BOOST_THREAD_USES_DATETIME
20 #include <boost/thread/xtime.hpp>
21 #endif
22
23 #ifdef BOOST_THREAD_USES_CHRONO
24 #include <boost/chrono/system_clocks.hpp>
25 #include <boost/chrono/ceil.hpp>
26 #endif
27 #include <boost/thread/detail/delete.hpp>
28 #include <boost/date_time/posix_time/posix_time_duration.hpp>
29
30 #include <algorithm>
31
32 #include <boost/config/abi_prefix.hpp>
33
34 namespace boost
35 {
36 class condition_variable
37 {
38 private:
39 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
40 pthread_mutex_t internal_mutex;
41 //#endif
42 pthread_cond_t cond;
43
44 public:
45 //private: // used by boost::thread::try_join_until
46
47 bool do_wait_until(
48 unique_lock<mutex>& lock,
49 detail::internal_platform_timepoint const &timeout);
50
51 public:
52 BOOST_THREAD_NO_COPYABLE(condition_variable)
53 condition_variable()
54 {
55 int res;
56 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
57 // Even if it is not used, the internal_mutex exists (see
58 // above) and must be initialized (etc) in case some
59 // compilation units provide interruptions and others
60 // don't.
61 res=posix::pthread_mutex_init(&internal_mutex);
62 if(res)
63 {
64 boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
65 }
66 //#endif
67 res = posix::pthread_cond_init(&cond);
68 if (res)
69 {
70 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
71 // ditto
72 BOOST_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
73 //#endif
74 boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_cond_init"));
75 }
76 }
77 ~condition_variable()
78 {
79 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
80 // ditto
81 BOOST_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
82 //#endif
83 BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
84 }
85
86 void wait(unique_lock<mutex>& m);
87
88 template<typename predicate_type>
89 void wait(unique_lock<mutex>& m,predicate_type pred)
90 {
91 while (!pred())
92 {
93 wait(m);
94 }
95 }
96
97 #if defined BOOST_THREAD_USES_DATETIME
98 bool timed_wait(
99 unique_lock<mutex>& m,
100 boost::system_time const& abs_time)
101 {
102 #if defined BOOST_THREAD_WAIT_BUG
103 const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
104 #else
105 const detail::real_platform_timepoint ts(abs_time);
106 #endif
107 #if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
108 // The system time may jump while this function is waiting. To compensate for this and time
109 // out near the correct time, we could call do_wait_until() in a loop with a short timeout
110 // and recheck the time remaining each time through the loop. However, because we can't
111 // check the predicate each time do_wait_until() completes, this introduces the possibility
112 // of not exiting the function when a notification occurs, since do_wait_until() may report
113 // that it timed out even though a notification was received. The best this function can do
114 // is report correctly whether or not it reached the timeout time.
115 const detail::platform_duration d(ts - detail::real_platform_clock::now());
116 do_wait_until(m, detail::internal_platform_clock::now() + d);
117 return ts > detail::real_platform_clock::now();
118 #else
119 return do_wait_until(m, ts);
120 #endif
121 }
122 bool timed_wait(
123 unique_lock<mutex>& m,
124 ::boost::xtime const& abs_time)
125 {
126 return timed_wait(m,system_time(abs_time));
127 }
128
129 template<typename duration_type>
130 bool timed_wait(
131 unique_lock<mutex>& m,
132 duration_type const& wait_duration)
133 {
134 if (wait_duration.is_pos_infinity())
135 {
136 wait(m);
137 return true;
138 }
139 if (wait_duration.is_special())
140 {
141 return true;
142 }
143 detail::platform_duration d(wait_duration);
144 #if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
145 // The system time may jump while this function is waiting. To compensate for this and time
146 // out near the correct time, we could call do_wait_until() in a loop with a short timeout
147 // and recheck the time remaining each time through the loop. However, because we can't
148 // check the predicate each time do_wait_until() completes, this introduces the possibility
149 // of not exiting the function when a notification occurs, since do_wait_until() may report
150 // that it timed out even though a notification was received. The best this function can do
151 // is report correctly whether or not it reached the timeout time.
152 const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
153 do_wait_until(m, detail::internal_platform_clock::now() + d);
154 return ts > detail::mono_platform_clock::now();
155 #else
156 return do_wait_until(m, detail::internal_platform_clock::now() + d);
157 #endif
158 }
159
160 template<typename predicate_type>
161 bool timed_wait(
162 unique_lock<mutex>& m,
163 boost::system_time const& abs_time,predicate_type pred)
164 {
165 #if defined BOOST_THREAD_WAIT_BUG
166 const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
167 #else
168 const detail::real_platform_timepoint ts(abs_time);
169 #endif
170 while (!pred())
171 {
172 #if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
173 // The system time may jump while this function is waiting. To compensate for this
174 // and time out near the correct time, we call do_wait_until() in a loop with a
175 // short timeout and recheck the time remaining each time through the loop.
176 detail::platform_duration d(ts - detail::real_platform_clock::now());
177 if (d <= detail::platform_duration::zero()) break; // timeout occurred
178 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
179 do_wait_until(m, detail::internal_platform_clock::now() + d);
180 #else
181 if (!do_wait_until(m, ts)) break; // timeout occurred
182 #endif
183 }
184 return pred();
185 }
186
187 template<typename predicate_type>
188 bool timed_wait(
189 unique_lock<mutex>& m,
190 ::boost::xtime const& abs_time,predicate_type pred)
191 {
192 return timed_wait(m,system_time(abs_time),pred);
193 }
194
195 template<typename duration_type,typename predicate_type>
196 bool timed_wait(
197 unique_lock<mutex>& m,
198 duration_type const& wait_duration,predicate_type pred)
199 {
200 if (wait_duration.is_pos_infinity())
201 {
202 while (!pred())
203 {
204 wait(m);
205 }
206 return true;
207 }
208 if (wait_duration.is_special())
209 {
210 return pred();
211 }
212 detail::platform_duration d(wait_duration);
213 #if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
214 // The system time may jump while this function is waiting. To compensate for this
215 // and time out near the correct time, we call do_wait_until() in a loop with a
216 // short timeout and recheck the time remaining each time through the loop.
217 const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
218 while (!pred())
219 {
220 if (d <= detail::platform_duration::zero()) break; // timeout occurred
221 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
222 do_wait_until(m, detail::internal_platform_clock::now() + d);
223 d = ts - detail::mono_platform_clock::now();
224 }
225 #else
226 const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
227 while (!pred())
228 {
229 if (!do_wait_until(m, ts)) break; // timeout occurred
230 }
231 #endif
232 return pred();
233 }
234 #endif
235
236 #ifdef BOOST_THREAD_USES_CHRONO
237
238 template <class Duration>
239 cv_status
240 wait_until(
241 unique_lock<mutex>& lock,
242 const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
243 {
244 const detail::internal_platform_timepoint ts(t);
245 if (do_wait_until(lock, ts)) return cv_status::no_timeout;
246 else return cv_status::timeout;
247 }
248
249 template <class Clock, class Duration>
250 cv_status
251 wait_until(
252 unique_lock<mutex>& lock,
253 const chrono::time_point<Clock, Duration>& t)
254 {
255 // The system time may jump while this function is waiting. To compensate for this and time
256 // out near the correct time, we could call do_wait_until() in a loop with a short timeout
257 // and recheck the time remaining each time through the loop. However, because we can't
258 // check the predicate each time do_wait_until() completes, this introduces the possibility
259 // of not exiting the function when a notification occurs, since do_wait_until() may report
260 // that it timed out even though a notification was received. The best this function can do
261 // is report correctly whether or not it reached the timeout time.
262 typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
263 common_duration d(t - Clock::now());
264 do_wait_until(lock, detail::internal_chrono_clock::now() + d);
265 if (t > Clock::now()) return cv_status::no_timeout;
266 else return cv_status::timeout;
267 }
268
269 template <class Rep, class Period>
270 cv_status
271 wait_for(
272 unique_lock<mutex>& lock,
273 const chrono::duration<Rep, Period>& d)
274 {
275 return wait_until(lock, chrono::steady_clock::now() + d);
276 }
277
278 template <class Duration, class Predicate>
279 bool
280 wait_until(
281 unique_lock<mutex>& lock,
282 const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
283 Predicate pred)
284 {
285 const detail::internal_platform_timepoint ts(t);
286 while (!pred())
287 {
288 if (!do_wait_until(lock, ts)) break; // timeout occurred
289 }
290 return pred();
291 }
292
293 template <class Clock, class Duration, class Predicate>
294 bool
295 wait_until(
296 unique_lock<mutex>& lock,
297 const chrono::time_point<Clock, Duration>& t,
298 Predicate pred)
299 {
300 // The system time may jump while this function is waiting. To compensate for this
301 // and time out near the correct time, we call do_wait_until() in a loop with a
302 // short timeout and recheck the time remaining each time through the loop.
303 typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
304 while (!pred())
305 {
306 common_duration d(t - Clock::now());
307 if (d <= common_duration::zero()) break; // timeout occurred
308 d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
309 do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
310 }
311 return pred();
312 }
313
314 template <class Rep, class Period, class Predicate>
315 bool
316 wait_for(
317 unique_lock<mutex>& lock,
318 const chrono::duration<Rep, Period>& d,
319 Predicate pred)
320 {
321 return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
322 }
323 #endif
324
325 #define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE
326 typedef pthread_cond_t* native_handle_type;
327 native_handle_type native_handle()
328 {
329 return &cond;
330 }
331
332 void notify_one() BOOST_NOEXCEPT;
333 void notify_all() BOOST_NOEXCEPT;
334 };
335
336 BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
337 }
338
339 #include <boost/config/abi_suffix.hpp>
340
341 #endif