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
9 #include <boost/assert.hpp>
10 #include <boost/throw_exception.hpp>
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>
19 #if defined BOOST_THREAD_USES_DATETIME
20 #include <boost/thread/xtime.hpp>
23 #ifdef BOOST_THREAD_USES_CHRONO
24 #include <boost/chrono/system_clocks.hpp>
25 #include <boost/chrono/ceil.hpp>
27 #include <boost/thread/detail/delete.hpp>
28 #include <boost/date_time/posix_time/posix_time_duration.hpp>
32 #include <boost/config/abi_prefix.hpp>
36 class condition_variable
39 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
40 pthread_mutex_t internal_mutex;
45 //private: // used by boost::thread::try_join_until
48 unique_lock<mutex>& lock,
49 detail::internal_platform_timepoint const &timeout);
52 BOOST_THREAD_NO_COPYABLE(condition_variable)
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
61 res=pthread_mutex_init(&internal_mutex,NULL);
64 boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
67 res = pthread::cond_init(cond);
70 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
72 BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
74 boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread::cond_init"));
80 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
83 ret = pthread_mutex_destroy(&internal_mutex);
84 } while (ret == EINTR);
88 ret = pthread_cond_destroy(&cond);
89 } while (ret == EINTR);
93 void wait(unique_lock<mutex>& m);
95 template<typename predicate_type>
96 void wait(unique_lock<mutex>& m,predicate_type pred)
104 #if defined BOOST_THREAD_USES_DATETIME
106 unique_lock<mutex>& m,
107 boost::system_time const& abs_time)
109 #if defined BOOST_THREAD_WAIT_BUG
110 const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
112 const detail::real_platform_timepoint ts(abs_time);
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();
126 return do_wait_until(m, ts);
130 unique_lock<mutex>& m,
131 xtime const& abs_time)
133 return timed_wait(m,system_time(abs_time));
136 template<typename duration_type>
138 unique_lock<mutex>& m,
139 duration_type const& wait_duration)
141 if (wait_duration.is_pos_infinity())
146 if (wait_duration.is_special())
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();
163 return do_wait_until(m, detail::internal_platform_clock::now() + d);
167 template<typename predicate_type>
169 unique_lock<mutex>& m,
170 boost::system_time const& abs_time,predicate_type pred)
172 #if defined BOOST_THREAD_WAIT_BUG
173 const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
175 const detail::real_platform_timepoint ts(abs_time);
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);
188 if (!do_wait_until(m, ts)) break; // timeout occurred
194 template<typename predicate_type>
196 unique_lock<mutex>& m,
197 xtime const& abs_time,predicate_type pred)
199 return timed_wait(m,system_time(abs_time),pred);
202 template<typename duration_type,typename predicate_type>
204 unique_lock<mutex>& m,
205 duration_type const& wait_duration,predicate_type pred)
207 if (wait_duration.is_pos_infinity())
215 if (wait_duration.is_special())
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);
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();
233 const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
236 if (!do_wait_until(m, ts)) break; // timeout occurred
243 #ifdef BOOST_THREAD_USES_CHRONO
245 template <class Duration>
248 unique_lock<mutex>& lock,
249 const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
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;
256 template <class Clock, class Duration>
259 unique_lock<mutex>& lock,
260 const chrono::time_point<Clock, Duration>& t)
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;
276 template <class Rep, class Period>
279 unique_lock<mutex>& lock,
280 const chrono::duration<Rep, Period>& d)
282 return wait_until(lock, chrono::steady_clock::now() + d);
285 template <class Duration, class Predicate>
288 unique_lock<mutex>& lock,
289 const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
292 const detail::internal_platform_timepoint ts(t);
295 if (!do_wait_until(lock, ts)) break; // timeout occurred
300 template <class Clock, class Duration, class Predicate>
303 unique_lock<mutex>& lock,
304 const chrono::time_point<Clock, Duration>& t,
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;
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));
321 template <class Rep, class Period, class Predicate>
324 unique_lock<mutex>& lock,
325 const chrono::duration<Rep, Period>& d,
328 return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
332 #define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE
333 typedef pthread_cond_t* native_handle_type;
334 native_handle_type native_handle()
339 void notify_one() BOOST_NOEXCEPT;
340 void notify_all() BOOST_NOEXCEPT;
343 BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
346 #include <boost/config/abi_suffix.hpp>