]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/thread/pthread/condition_variable_fwd.hpp
update sources to ceph Nautilus 14.2.1
[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=pthread_mutex_init(&internal_mutex,NULL);
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 = pthread::cond_init(cond);
68 if (res)
69 {
70 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
71 // ditto
72 BOOST_VERIFY(!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 int ret;
80 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
81 // ditto
82 do {
83 ret = pthread_mutex_destroy(&internal_mutex);
84 } while (ret == EINTR);
85 BOOST_ASSERT(!ret);
86 //#endif
87 do {
88 ret = pthread_cond_destroy(&cond);
89 } while (ret == EINTR);
90 BOOST_ASSERT(!ret);
91 }
92
93 void wait(unique_lock<mutex>& m);
94
95 template<typename predicate_type>
96 void wait(unique_lock<mutex>& m,predicate_type pred)
97 {
98 while (!pred())
99 {
100 wait(m);
101 }
102 }
103
104 #if defined BOOST_THREAD_USES_DATETIME
105 bool timed_wait(
106 unique_lock<mutex>& m,
107 boost::system_time const& abs_time)
108 {
109 #if defined BOOST_THREAD_WAIT_BUG
110 const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
111 #else
112 const detail::real_platform_timepoint ts(abs_time);
113 #endif
114 #if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
115 // The system time may jump while this function is waiting. To compensate for this and time
116 // out near the correct time, we could call do_wait_until() in a loop with a short timeout
117 // and recheck the time remaining each time through the loop. However, because we can't
118 // check the predicate each time do_wait_until() completes, this introduces the possibility
119 // of not exiting the function when a notification occurs, since do_wait_until() may report
120 // that it timed out even though a notification was received. The best this function can do
121 // is report correctly whether or not it reached the timeout time.
122 const detail::platform_duration d(ts - detail::real_platform_clock::now());
123 do_wait_until(m, detail::internal_platform_clock::now() + d);
124 return ts > detail::real_platform_clock::now();
125 #else
126 return do_wait_until(m, ts);
127 #endif
128 }
129 bool timed_wait(
130 unique_lock<mutex>& m,
131 xtime const& abs_time)
132 {
133 return timed_wait(m,system_time(abs_time));
134 }
135
136 template<typename duration_type>
137 bool timed_wait(
138 unique_lock<mutex>& m,
139 duration_type const& wait_duration)
140 {
141 if (wait_duration.is_pos_infinity())
142 {
143 wait(m);
144 return true;
145 }
146 if (wait_duration.is_special())
147 {
148 return true;
149 }
150 detail::platform_duration d(wait_duration);
151 #if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
152 // The system time may jump while this function is waiting. To compensate for this and time
153 // out near the correct time, we could call do_wait_until() in a loop with a short timeout
154 // and recheck the time remaining each time through the loop. However, because we can't
155 // check the predicate each time do_wait_until() completes, this introduces the possibility
156 // of not exiting the function when a notification occurs, since do_wait_until() may report
157 // that it timed out even though a notification was received. The best this function can do
158 // is report correctly whether or not it reached the timeout time.
159 const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
160 do_wait_until(m, detail::internal_platform_clock::now() + d);
161 return ts > detail::mono_platform_clock::now();
162 #else
163 return do_wait_until(m, detail::internal_platform_clock::now() + d);
164 #endif
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 #if defined BOOST_THREAD_WAIT_BUG
173 const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
174 #else
175 const detail::real_platform_timepoint ts(abs_time);
176 #endif
177 while (!pred())
178 {
179 #if defined BOOST_THREAD_INTERNAL_CLOCK_IS_MONO
180 // The system time may jump while this function is waiting. To compensate for this
181 // and time out near the correct time, we call do_wait_until() in a loop with a
182 // short timeout and recheck the time remaining each time through the loop.
183 detail::platform_duration d(ts - detail::real_platform_clock::now());
184 if (d <= detail::platform_duration::zero()) break; // timeout occurred
185 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
186 do_wait_until(m, detail::internal_platform_clock::now() + d);
187 #else
188 if (!do_wait_until(m, ts)) break; // timeout occurred
189 #endif
190 }
191 return pred();
192 }
193
194 template<typename predicate_type>
195 bool timed_wait(
196 unique_lock<mutex>& m,
197 xtime const& abs_time,predicate_type pred)
198 {
199 return timed_wait(m,system_time(abs_time),pred);
200 }
201
202 template<typename duration_type,typename predicate_type>
203 bool timed_wait(
204 unique_lock<mutex>& m,
205 duration_type const& wait_duration,predicate_type pred)
206 {
207 if (wait_duration.is_pos_infinity())
208 {
209 while (!pred())
210 {
211 wait(m);
212 }
213 return true;
214 }
215 if (wait_duration.is_special())
216 {
217 return pred();
218 }
219 detail::platform_duration d(wait_duration);
220 #if defined(BOOST_THREAD_HAS_MONO_CLOCK) && !defined(BOOST_THREAD_INTERNAL_CLOCK_IS_MONO)
221 // The system time may jump while this function is waiting. To compensate for this
222 // and time out near the correct time, we call do_wait_until() in a loop with a
223 // short timeout and recheck the time remaining each time through the loop.
224 const detail::mono_platform_timepoint ts(detail::mono_platform_clock::now() + d);
225 while (!pred())
226 {
227 if (d <= detail::platform_duration::zero()) break; // timeout occurred
228 d = (std::min)(d, detail::platform_milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS));
229 do_wait_until(m, detail::internal_platform_clock::now() + d);
230 d = ts - detail::mono_platform_clock::now();
231 }
232 #else
233 const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
234 while (!pred())
235 {
236 if (!do_wait_until(m, ts)) break; // timeout occurred
237 }
238 #endif
239 return pred();
240 }
241 #endif
242
243 #ifdef BOOST_THREAD_USES_CHRONO
244
245 template <class Duration>
246 cv_status
247 wait_until(
248 unique_lock<mutex>& lock,
249 const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
250 {
251 const detail::internal_platform_timepoint ts(t);
252 if (do_wait_until(lock, ts)) return cv_status::no_timeout;
253 else return cv_status::timeout;
254 }
255
256 template <class Clock, class Duration>
257 cv_status
258 wait_until(
259 unique_lock<mutex>& lock,
260 const chrono::time_point<Clock, Duration>& t)
261 {
262 // The system time may jump while this function is waiting. To compensate for this and time
263 // out near the correct time, we could call do_wait_until() in a loop with a short timeout
264 // and recheck the time remaining each time through the loop. However, because we can't
265 // check the predicate each time do_wait_until() completes, this introduces the possibility
266 // of not exiting the function when a notification occurs, since do_wait_until() may report
267 // that it timed out even though a notification was received. The best this function can do
268 // is report correctly whether or not it reached the timeout time.
269 typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
270 common_duration d(t - Clock::now());
271 do_wait_until(lock, detail::internal_chrono_clock::now() + d);
272 if (t > Clock::now()) return cv_status::no_timeout;
273 else return cv_status::timeout;
274 }
275
276 template <class Rep, class Period>
277 cv_status
278 wait_for(
279 unique_lock<mutex>& lock,
280 const chrono::duration<Rep, Period>& d)
281 {
282 return wait_until(lock, chrono::steady_clock::now() + d);
283 }
284
285 template <class Duration, class Predicate>
286 bool
287 wait_until(
288 unique_lock<mutex>& lock,
289 const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
290 Predicate pred)
291 {
292 const detail::internal_platform_timepoint ts(t);
293 while (!pred())
294 {
295 if (!do_wait_until(lock, ts)) break; // timeout occurred
296 }
297 return pred();
298 }
299
300 template <class Clock, class Duration, class Predicate>
301 bool
302 wait_until(
303 unique_lock<mutex>& lock,
304 const chrono::time_point<Clock, Duration>& t,
305 Predicate pred)
306 {
307 // The system time may jump while this function is waiting. To compensate for this
308 // and time out near the correct time, we call do_wait_until() in a loop with a
309 // short timeout and recheck the time remaining each time through the loop.
310 typedef typename common_type<Duration, typename Clock::duration>::type common_duration;
311 while (!pred())
312 {
313 common_duration d(t - Clock::now());
314 if (d <= common_duration::zero()) break; // timeout occurred
315 d = (std::min)(d, common_duration(chrono::milliseconds(BOOST_THREAD_POLL_INTERVAL_MILLISECONDS)));
316 do_wait_until(lock, detail::internal_platform_clock::now() + detail::platform_duration(d));
317 }
318 return pred();
319 }
320
321 template <class Rep, class Period, class Predicate>
322 bool
323 wait_for(
324 unique_lock<mutex>& lock,
325 const chrono::duration<Rep, Period>& d,
326 Predicate pred)
327 {
328 return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
329 }
330 #endif
331
332 #define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE
333 typedef pthread_cond_t* native_handle_type;
334 native_handle_type native_handle()
335 {
336 return &cond;
337 }
338
339 void notify_one() BOOST_NOEXCEPT;
340 void notify_all() BOOST_NOEXCEPT;
341 };
342
343 BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
344 }
345
346 #include <boost/config/abi_suffix.hpp>
347
348 #endif