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/pthread/timespec.hpp>
17 #if defined BOOST_THREAD_USES_DATETIME
18 #include <boost/thread/xtime.hpp>
21 #ifdef BOOST_THREAD_USES_CHRONO
22 #include <boost/chrono/system_clocks.hpp>
23 #include <boost/chrono/ceil.hpp>
25 #include <boost/thread/detail/delete.hpp>
26 #include <boost/date_time/posix_time/posix_time_duration.hpp>
28 #include <boost/config/abi_prefix.hpp>
33 inline int monotonic_pthread_cond_init(pthread_cond_t& cond) {
35 #ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
36 pthread_condattr_t attr;
37 int res = pthread_condattr_init(&attr);
42 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
43 res=pthread_cond_init(&cond,&attr);
44 pthread_condattr_destroy(&attr);
47 return pthread_cond_init(&cond,NULL);
53 class condition_variable
56 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
57 pthread_mutex_t internal_mutex;
62 //private: // used by boost::thread::try_join_until
64 inline bool do_wait_until(
65 unique_lock<mutex>& lock,
66 struct timespec const &timeout);
69 unique_lock<mutex>& lock,
70 struct timespec const &timeout)
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()));
75 // old behavior was fine for monotonic
76 return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_realtime()));
81 BOOST_THREAD_NO_COPYABLE(condition_variable)
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
90 res=pthread_mutex_init(&internal_mutex,NULL);
93 boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
96 res = detail::monotonic_pthread_cond_init(cond);
99 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
101 BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
103 boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init"));
106 ~condition_variable()
109 //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
112 ret = pthread_mutex_destroy(&internal_mutex);
113 } while (ret == EINTR);
117 ret = pthread_cond_destroy(&cond);
118 } while (ret == EINTR);
122 void wait(unique_lock<mutex>& m);
124 template<typename predicate_type>
125 void wait(unique_lock<mutex>& m,predicate_type pred)
127 while(!pred()) wait(m);
130 #if defined BOOST_THREAD_USES_DATETIME
131 inline bool timed_wait(
132 unique_lock<mutex>& m,
133 boost::system_time const& abs_time)
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);
139 struct timespec const timeout=detail::to_timespec(abs_time);
140 return do_wait_until(m, timeout);
144 unique_lock<mutex>& m,
145 xtime const& abs_time)
147 return timed_wait(m,system_time(abs_time));
150 template<typename duration_type>
152 unique_lock<mutex>& m,
153 duration_type const& wait_duration)
155 if (wait_duration.is_pos_infinity())
157 wait(m); // or do_wait(m,detail::timeout::sentinel());
160 if (wait_duration.is_special())
164 return timed_wait(m,get_system_time()+wait_duration);
167 template<typename predicate_type>
169 unique_lock<mutex>& m,
170 boost::system_time const& abs_time,predicate_type pred)
174 if(!timed_wait(m, abs_time))
180 template<typename predicate_type>
182 unique_lock<mutex>& m,
183 xtime const& abs_time,predicate_type pred)
185 return timed_wait(m,system_time(abs_time),pred);
188 template<typename duration_type,typename predicate_type>
190 unique_lock<mutex>& m,
191 duration_type const& wait_duration,predicate_type pred)
193 if (wait_duration.is_pos_infinity())
197 wait(m); // or do_wait(m,detail::timeout::sentinel());
201 if (wait_duration.is_special())
205 return timed_wait(m,get_system_time()+wait_duration,pred);
209 #ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
211 #ifdef BOOST_THREAD_USES_CHRONO
213 template <class Duration>
216 unique_lock<mutex>& lock,
217 const chrono::time_point<chrono::system_clock, Duration>& t)
219 using namespace chrono;
220 typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
222 nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
223 return system_clock::now() < t ? cv_status::no_timeout :
227 template <class Clock, class Duration>
230 unique_lock<mutex>& lock,
231 const chrono::time_point<Clock, Duration>& t)
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;
242 template <class Rep, class Period>
245 unique_lock<mutex>& lock,
246 const chrono::duration<Rep, Period>& d)
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 :
257 inline cv_status wait_until(
258 unique_lock<mutex>& lk,
259 chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
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;
269 #else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
270 #ifdef BOOST_THREAD_USES_CHRONO
272 template <class Duration>
275 unique_lock<mutex>& lock,
276 const chrono::time_point<chrono::steady_clock, Duration>& t)
278 using namespace chrono;
279 typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
281 nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
282 return steady_clock::now() < t ? cv_status::no_timeout :
286 template <class Clock, class Duration>
289 unique_lock<mutex>& lock,
290 const chrono::time_point<Clock, Duration>& t)
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;
299 template <class Rep, class Period>
302 unique_lock<mutex>& lock,
303 const chrono::duration<Rep, Period>& d)
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 :
312 inline cv_status wait_until(
313 unique_lock<mutex>& lk,
314 chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
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;
324 #endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
326 #ifdef BOOST_THREAD_USES_CHRONO
327 template <class Clock, class Duration, class Predicate>
330 unique_lock<mutex>& lock,
331 const chrono::time_point<Clock, Duration>& t,
336 if (wait_until(lock, t) == cv_status::timeout)
342 template <class Rep, class Period, class Predicate>
345 unique_lock<mutex>& lock,
346 const chrono::duration<Rep, Period>& d,
349 return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
353 #define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE
354 typedef pthread_cond_t* native_handle_type;
355 native_handle_type native_handle()
360 void notify_one() BOOST_NOEXCEPT;
361 void notify_all() BOOST_NOEXCEPT;
366 BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
371 #include <boost/config/abi_suffix.hpp>