29 #ifndef _GLIBCXX_CONDITION_VARIABLE
30 #define _GLIBCXX_CONDITION_VARIABLE 1
32 #pragma GCC system_header
34 #if __cplusplus < 201103L
46 #include <bits/shared_ptr.h>
49 #if __cplusplus > 201703L
50 #define __cpp_lib_jthread 201907L
54 #if defined(_GLIBCXX_HAS_GTHREADS)
56 namespace std _GLIBCXX_VISIBILITY(default)
58 _GLIBCXX_BEGIN_NAMESPACE_VERSION
76 #ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
81 typedef __gthread_cond_t __native_type;
83 #ifdef __GTHREAD_COND_INIT
84 __native_type _M_cond = __GTHREAD_COND_INIT;
86 __native_type _M_cond;
90 typedef __native_type* native_handle_type;
99 notify_one() noexcept;
102 notify_all() noexcept;
107 template<
typename _Predicate>
115 #ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
116 template<
typename _Duration>
120 {
return __wait_until_impl(__lock, __atime); }
123 template<
typename _Duration>
127 {
return __wait_until_impl(__lock, __atime); }
129 template<
typename _Clock,
typename _Duration>
134 #if __cplusplus > 201703L
135 static_assert(chrono::is_clock_v<_Clock>);
137 const typename _Clock::time_point __c_entry = _Clock::now();
138 const __clock_t::time_point __s_entry = __clock_t::now();
139 const auto __delta = __atime - __c_entry;
140 const auto __s_atime = __s_entry + __delta;
142 if (__wait_until_impl(__lock, __s_atime) == cv_status::no_timeout)
143 return cv_status::no_timeout;
147 if (_Clock::now() < __atime)
148 return cv_status::no_timeout;
149 return cv_status::timeout;
152 template<
typename _Clock,
typename _Duration,
typename _Predicate>
159 if (wait_until(__lock, __atime) == cv_status::timeout)
164 template<
typename _Rep,
typename _Period>
169 using __dur =
typename steady_clock::duration;
170 auto __reltime = chrono::duration_cast<__dur>(__rtime);
171 if (__reltime < __rtime)
173 return wait_until(__lock, steady_clock::now() + __reltime);
176 template<
typename _Rep,
typename _Period,
typename _Predicate>
182 using __dur =
typename steady_clock::duration;
183 auto __reltime = chrono::duration_cast<__dur>(__rtime);
184 if (__reltime < __rtime)
186 return wait_until(__lock, steady_clock::now() + __reltime,
195 #ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
196 template<
typename _Dur>
201 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
202 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
204 __gthread_time_t __ts =
206 static_cast<std::time_t
>(__s.time_since_epoch().count()),
207 static_cast<long>(__ns.count())
210 pthread_cond_clockwait(&_M_cond, __lock.mutex()->native_handle(),
214 return (steady_clock::now() < __atime
215 ? cv_status::no_timeout : cv_status::timeout);
219 template<
typename _Dur>
224 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
225 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
227 __gthread_time_t __ts =
229 static_cast<std::time_t
>(__s.time_since_epoch().count()),
230 static_cast<long>(__ns.count())
233 __gthread_cond_timedwait(&_M_cond, __lock.mutex()->native_handle(),
236 return (system_clock::now() < __atime
237 ? cv_status::no_timeout : cv_status::timeout);
244 struct __at_thread_exit_elt
246 __at_thread_exit_elt* _M_next;
247 void (*_M_cb)(
void*);
250 inline namespace _V2 {
256 #ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
265 template<
typename _Lock>
268 explicit _Unlock(_Lock& __lk) : _M_lock(__lk) { __lk.unlock(); }
270 ~_Unlock() noexcept(
false)
277 { __throw_exception_again; }
285 _Unlock(
const _Unlock&) =
delete;
286 _Unlock& operator=(
const _Unlock&) =
delete;
299 notify_one() noexcept
302 _M_cond.notify_one();
306 notify_all() noexcept
309 _M_cond.notify_all();
312 template<
typename _Lock>
318 _Unlock<_Lock> __unlock(__lock);
322 _M_cond.wait(__my_lock2);
326 template<
typename _Lock,
typename _Predicate>
328 wait(_Lock& __lock, _Predicate __p)
334 template<
typename _Lock,
typename _Clock,
typename _Duration>
336 wait_until(_Lock& __lock,
341 _Unlock<_Lock> __unlock(__lock);
345 return _M_cond.wait_until(__my_lock2, __atime);
348 template<
typename _Lock,
typename _Clock,
349 typename _Duration,
typename _Predicate>
351 wait_until(_Lock& __lock,
356 if (wait_until(__lock, __atime) == cv_status::timeout)
361 template<
typename _Lock,
typename _Rep,
typename _Period>
364 {
return wait_until(__lock, __clock_t::now() + __rtime); }
366 template<
typename _Lock,
typename _Rep,
367 typename _Period,
typename _Predicate>
369 wait_for(_Lock& __lock,
371 {
return wait_until(__lock, __clock_t::now() + __rtime,
std::move(__p)); }
373 #ifdef __cpp_lib_jthread
374 template <
class _Lock,
class _Predicate>
375 bool wait(_Lock& __lock,
379 if (__stoken.stop_requested())
384 std::stop_callback __cb(__stoken, [
this] { notify_all(); });
389 if (__stoken.stop_requested())
395 _Unlock<_Lock> __unlock(__lock);
397 _M_cond.wait(__my_lock2);
402 template <
class _Lock,
class _Clock,
class _Duration,
class _Predicate>
403 bool wait_until(_Lock& __lock,
408 if (__stoken.stop_requested())
413 std::stop_callback __cb(__stoken, [
this] { notify_all(); });
420 if (__stoken.stop_requested())
424 _Unlock<_Lock> __u(__lock);
426 const auto __status = _M_cond.wait_until(__my_lock2, __abs_time);
427 __stop = (__status == std::cv_status::timeout) || __stoken.stop_requested();
437 template <
class _Lock,
class _Rep,
class _Period,
class _Predicate>
438 bool wait_for(_Lock& __lock,
443 auto __abst = std::chrono::steady_clock::now() + __rel_time;
444 return wait_until(__lock,
455 _GLIBCXX_END_NAMESPACE_VERSION
458 #endif // _GLIBCXX_HAS_GTHREADS
460 #endif // _GLIBCXX_CONDITION_VARIABLE