1#ifndef _STDEX_CONDITION_VARIABLE_H
2#define _STDEX_CONDITION_VARIABLE_H
10#include "./system_error.hpp"
19#if defined(_DEBUG) || defined(DEBUG)
23#ifdef _STDEX_NATIVE_CPP11_SUPPORT
25#define _STDEX_DELETED_FUNCTION =delete
26#define _STDEX_NOEXCEPT_FUNCTION noexcept
27#define _STDEX_NOEXCEPT(args) noexcept(args)
31#define _STDEX_DELETED_FUNCTION
32#define _STDEX_NOEXCEPT_FUNCTION throw()
33#define _STDEX_NOEXCEPT(args)
47 pthread_mutex_t* _lock_mutex_native_handle(
const unique_lock<mutex>&);
48 bool _lock_owns_lock(
const unique_lock<mutex>&);
58 static void _throw_system_error(
const _Tp &_errc)
60 throw stdex::system_error(
61 stdex::make_error_code(_errc));
68 enum cv_status_t { no_timeout, timeout };
76 operator cv_status_t()
const
87 template<
class _Clock,
class _Dur,
class _WaitUntilClock>
88 struct _sync_unknown_clock
90 typedef _Clock _Clock_local;
91 typedef _Dur _Dur_local;
92 typedef typename _Clock_local::time_point _Clock_time_point;
94 static chrono::time_point<_WaitUntilClock, _Dur_local> sync_clock_tp(
const chrono::time_point<_Clock_local, _Dur_local>& _atime, ...)
96 const _Clock_time_point _c_entry = _Clock_local::now();
97 const typename _WaitUntilClock::time_point _s_entry = _WaitUntilClock::now();
99 _Dur_local _delta = (_atime - _c_entry);
100 return (_s_entry + stdex::chrono::duration_cast<typename _WaitUntilClock::duration>(_delta));
103 static const chrono::time_point<_WaitUntilClock, _Dur_local>& sync_clock_tp(
const chrono::time_point<_WaitUntilClock, _Dur_local>& _atime,
int)
110 class condition_variable
113 typedef pthread_cond_t* native_handle_type;
118 pthread_cond_init(&_condition_handle, NULL);
123 stdex::make_error_code(stdex::errc::errc_t(_err))
128 ~condition_variable() _STDEX_NOEXCEPT(false)
131 pthread_cond_destroy(&_condition_handle);
134 detail::_throw_system_error(stdex::errc::errc_t(_err));
137 inline void wait(unique_lock<mutex> &_lock) _STDEX_NOEXCEPT_FUNCTION
140 pthread_cond_wait(&_condition_handle, detail::_lock_mutex_native_handle(_lock));
144 #if defined(_DEBUG) || defined(DEBUG)
145 std::cerr << stdex::error_code(
146 stdex::make_error_code(stdex::errc::errc_t(_err))
147 ).message() << std::endl;
153 template<
class _Predicate>
154 void wait(unique_lock<mutex>& _lock, _Predicate _p)
160 template<
class _Clock,
class _Duration>
161 cv_status wait_until(unique_lock<mutex> &_lock,
const chrono::time_point<_Clock, _Duration> &_atime)
163 return wait_until_impl(_lock, _atime);
166 template<
class _Clock,
class _Duration,
class _Predicate>
167 bool wait_until(unique_lock<mutex> &_lock,
const chrono::time_point<_Clock, _Duration> &_atime, _Predicate _p)
170 if (wait_until(_lock, _atime) == cv_status::timeout)
175 template<
class _Rep,
class _Period>
176 cv_status wait_for(unique_lock<mutex> &_lock,
const chrono::duration<_Rep, _Period> &_rtime)
178 return wait_for_impl(_lock, _rtime);
181 template<
class _Rep,
class _Period,
class _Predicate>
182 bool wait_for(unique_lock<mutex> &_lock,
const chrono::duration<_Rep, _Period> &_rtime, _Predicate _p)
184 typedef chrono::system_clock sync_clock;
186 sync_clock::time_point _atime =
187 sync_clock::now() + chrono::duration_cast<sync_clock::duration>(_rtime);
191 if (wait_until(_lock, _atime) == cv_status::timeout)
196 native_handle_type native_handle()
198 return &_condition_handle;
201 inline void notify_one() _STDEX_NOEXCEPT_FUNCTION
203 pthread_cond_signal(&_condition_handle);
206 inline void notify_all() _STDEX_NOEXCEPT_FUNCTION
208 pthread_cond_broadcast(&_condition_handle);
213 template<
class _Clock,
class _Dur>
214 cv_status wait_until_impl(unique_lock<mutex> &_lock,
const chrono::time_point<_Clock, _Dur> &_atime)
216 if (!detail::_lock_owns_lock(_lock))
219 typedef chrono::system_clock wait_until_clock;
224 wait_until_clock::time_point _tp = chrono::time_point_cast<wait_until_clock::duration>(
225 detail::_sync_unknown_clock<_Clock, _Dur, wait_until_clock>::sync_clock_tp(_atime, 0)
228 if (_tp < wait_until_clock::now())
229 return cv_status::timeout;
231 stdex::timespec _tp_as_ts =
232 wait_until_clock::to_timespec(
238 _ts.tv_nsec = _tp_as_ts.tv_nsec;
239 _ts.tv_sec = _tp_as_ts.tv_sec;
242 pthread_cond_timedwait(&_condition_handle, detail::_lock_mutex_native_handle(_lock), &_ts);
245 if(_err && _err != ETIMEDOUT)
247 #if defined(_DEBUG) || defined(DEBUG)
248 std::cerr << stdex::error_code(
249 stdex::make_error_code(stdex::errc::errc_t(_err))
250 ).message() << std::endl;
256 return (wait_until_clock::now() < _tp
257 ? cv_status::no_timeout : cv_status::timeout);
260 template<
class _Rep,
class _Period>
261 cv_status wait_for_impl(unique_lock<mutex> &_lock, chrono::duration<_Rep, _Period> _rtime)
263 if (!detail::_lock_owns_lock(_lock))
266 if (_rtime.count() < 0)
267 return cv_status::timeout;
269 typedef chrono::system_clock time_measurment_clock;
270 typedef chrono::system_clock wait_for_clock;
272 if (ratio_greater<time_measurment_clock::period, _Period>::value)
275 time_measurment_clock::time_point
276 _start_time_point = time_measurment_clock::now(),
277 _end_time_point = _start_time_point + stdex::chrono::duration_cast<time_measurment_clock::duration>(_rtime);
279 stdex::timespec _tp_as_ts =
280 wait_for_clock::to_timespec(wait_for_clock::now() + stdex::chrono::duration_cast<wait_for_clock::duration>(_rtime));
283 _ts.tv_sec = _tp_as_ts.tv_sec;
284 _ts.tv_nsec = _tp_as_ts.tv_nsec;
286 if ((time_measurment_clock::now() - _start_time_point) > _rtime)
287 return cv_status::timeout;
290 pthread_cond_timedwait(&_condition_handle, detail::_lock_mutex_native_handle(_lock), &_ts);
293 if(_err && _err != ETIMEDOUT)
295 #if defined(_DEBUG) || defined(DEBUG)
296 std::cerr << stdex::error_code(
297 stdex::make_error_code(stdex::errc::errc_t(_err))
298 ).message() << std::endl;
304 return (time_measurment_clock::now() - _start_time_point < _rtime
305 ? cv_status::no_timeout : cv_status::timeout);
308 pthread_cond_t _condition_handle;
310 condition_variable(
const condition_variable&) _STDEX_DELETED_FUNCTION;
311 condition_variable& operator=(
const condition_variable&) _STDEX_DELETED_FUNCTION;
314 void notify_all_at_thread_exit(condition_variable &cond, unique_lock<mutex> &lk);
317#undef _STDEX_DELETED_FUNCTION
318#undef _STDEX_NOEXCEPT_FUNCTION
319#undef _STDEX_NOEXCEPT
cv_status
Definition: condition_variable.hpp:67