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=posix::pthread_mutex_init(&internal_mutex);
64 boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
67 res = posix::pthread_cond_init(&cond);
70 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
72 BOOST_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
74 boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_cond_init"));
79 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
81 BOOST_VERIFY(!posix::pthread_mutex_destroy(&internal_mutex));
83 BOOST_VERIFY(!posix::pthread_cond_destroy(&cond));
86 void wait(unique_lock<mutex>& m);
88 template<typename predicate_type>
89 void wait(unique_lock<mutex>& m,predicate_type pred)
97 #if defined BOOST_THREAD_USES_DATETIME
99 unique_lock<mutex>& m,
100 boost::system_time const& abs_time)
102 #if defined BOOST_THREAD_WAIT_BUG
103 const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
105 const detail::real_platform_timepoint ts(abs_time);
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();
119 return do_wait_until(m, ts);
123 unique_lock<mutex>& m,
124 ::boost::xtime const& abs_time)
126 return timed_wait(m,system_time(abs_time));
129 template<typename duration_type>
131 unique_lock<mutex>& m,
132 duration_type const& wait_duration)
134 if (wait_duration.is_pos_infinity())
139 if (wait_duration.is_special())
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();
156 return do_wait_until(m, detail::internal_platform_clock::now() + d);
160 template<typename predicate_type>
162 unique_lock<mutex>& m,
163 boost::system_time const& abs_time,predicate_type pred)
165 #if defined BOOST_THREAD_WAIT_BUG
166 const detail::real_platform_timepoint ts(abs_time + BOOST_THREAD_WAIT_BUG);
168 const detail::real_platform_timepoint ts(abs_time);
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);
181 if (!do_wait_until(m, ts)) break; // timeout occurred
187 template<typename predicate_type>
189 unique_lock<mutex>& m,
190 ::boost::xtime const& abs_time,predicate_type pred)
192 return timed_wait(m,system_time(abs_time),pred);
195 template<typename duration_type,typename predicate_type>
197 unique_lock<mutex>& m,
198 duration_type const& wait_duration,predicate_type pred)
200 if (wait_duration.is_pos_infinity())
208 if (wait_duration.is_special())
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);
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();
226 const detail::internal_platform_timepoint ts(detail::internal_platform_clock::now() + d);
229 if (!do_wait_until(m, ts)) break; // timeout occurred
236 #ifdef BOOST_THREAD_USES_CHRONO
238 template <class Duration>
241 unique_lock<mutex>& lock,
242 const chrono::time_point<detail::internal_chrono_clock, Duration>& t)
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;
249 template <class Clock, class Duration>
252 unique_lock<mutex>& lock,
253 const chrono::time_point<Clock, Duration>& t)
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;
269 template <class Rep, class Period>
272 unique_lock<mutex>& lock,
273 const chrono::duration<Rep, Period>& d)
275 return wait_until(lock, chrono::steady_clock::now() + d);
278 template <class Duration, class Predicate>
281 unique_lock<mutex>& lock,
282 const chrono::time_point<detail::internal_chrono_clock, Duration>& t,
285 const detail::internal_platform_timepoint ts(t);
288 if (!do_wait_until(lock, ts)) break; // timeout occurred
293 template <class Clock, class Duration, class Predicate>
296 unique_lock<mutex>& lock,
297 const chrono::time_point<Clock, Duration>& t,
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;
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));
314 template <class Rep, class Period, class Predicate>
317 unique_lock<mutex>& lock,
318 const chrono::duration<Rep, Period>& d,
321 return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
325 #define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE
326 typedef pthread_cond_t* native_handle_type;
327 native_handle_type native_handle()
332 void notify_one() BOOST_NOEXCEPT;
333 void notify_all() BOOST_NOEXCEPT;
336 BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
339 #include <boost/config/abi_suffix.hpp>