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 const typename _Clock::time_point __c_entry = _Clock::now();
135 const __clock_t::time_point __s_entry = __clock_t::now();
136 const auto __delta = __atime - __c_entry;
137 const auto __s_atime = __s_entry + __delta;
139 if (__wait_until_impl(__lock, __s_atime) == cv_status::no_timeout)
140 return cv_status::no_timeout;
144 if (_Clock::now() < __atime)
145 return cv_status::no_timeout;
146 return cv_status::timeout;
149 template<
typename _Clock,
typename _Duration,
typename _Predicate>
156 if (wait_until(__lock, __atime) == cv_status::timeout)
161 template<
typename _Rep,
typename _Period>
166 using __dur =
typename steady_clock::duration;
167 auto __reltime = chrono::duration_cast<__dur>(__rtime);
168 if (__reltime < __rtime)
170 return wait_until(__lock, steady_clock::now() + __reltime);
173 template<
typename _Rep,
typename _Period,
typename _Predicate>
179 using __dur =
typename steady_clock::duration;
180 auto __reltime = chrono::duration_cast<__dur>(__rtime);
181 if (__reltime < __rtime)
183 return wait_until(__lock, steady_clock::now() + __reltime,
192 #ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
193 template<
typename _Dur>
198 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
199 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
201 __gthread_time_t __ts =
203 static_cast<std::time_t
>(__s.time_since_epoch().count()),
204 static_cast<long>(__ns.count())
207 pthread_cond_clockwait(&_M_cond, __lock.mutex()->native_handle(),
211 return (steady_clock::now() < __atime
212 ? cv_status::no_timeout : cv_status::timeout);
216 template<
typename _Dur>
221 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
222 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
224 __gthread_time_t __ts =
226 static_cast<std::time_t
>(__s.time_since_epoch().count()),
227 static_cast<long>(__ns.count())
230 __gthread_cond_timedwait(&_M_cond, __lock.mutex()->native_handle(),
233 return (system_clock::now() < __atime
234 ? cv_status::no_timeout : cv_status::timeout);
241 struct __at_thread_exit_elt
243 __at_thread_exit_elt* _M_next;
244 void (*_M_cb)(
void*);
247 inline namespace _V2 {
253 #ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
262 template<
typename _Lock>
265 explicit _Unlock(_Lock& __lk) : _M_lock(__lk) { __lk.unlock(); }
267 ~_Unlock() noexcept(
false)
274 { __throw_exception_again; }
282 _Unlock(
const _Unlock&) =
delete;
283 _Unlock& operator=(
const _Unlock&) =
delete;
296 notify_one() noexcept
299 _M_cond.notify_one();
303 notify_all() noexcept
306 _M_cond.notify_all();
309 template<
typename _Lock>
315 _Unlock<_Lock> __unlock(__lock);
319 _M_cond.wait(__my_lock2);
323 template<
typename _Lock,
typename _Predicate>
325 wait(_Lock& __lock, _Predicate __p)
331 template<
typename _Lock,
typename _Clock,
typename _Duration>
333 wait_until(_Lock& __lock,
338 _Unlock<_Lock> __unlock(__lock);
342 return _M_cond.wait_until(__my_lock2, __atime);
345 template<
typename _Lock,
typename _Clock,
346 typename _Duration,
typename _Predicate>
348 wait_until(_Lock& __lock,
353 if (wait_until(__lock, __atime) == cv_status::timeout)
358 template<
typename _Lock,
typename _Rep,
typename _Period>
361 {
return wait_until(__lock, __clock_t::now() + __rtime); }
363 template<
typename _Lock,
typename _Rep,
364 typename _Period,
typename _Predicate>
366 wait_for(_Lock& __lock,
368 {
return wait_until(__lock, __clock_t::now() + __rtime,
std::move(__p)); }
370 #ifdef __cpp_lib_jthread
371 template <
class _Lock,
class _Predicate>
372 bool wait(_Lock& __lock,
376 if (__stoken.stop_requested())
381 std::stop_callback __cb(__stoken, [
this] { notify_all(); });
386 if (__stoken.stop_requested())
392 _Unlock<_Lock> __unlock(__lock);
394 _M_cond.wait(__my_lock2);
399 template <
class _Lock,
class _Clock,
class _Duration,
class _Predicate>
400 bool wait_until(_Lock& __lock,
405 if (__stoken.stop_requested())
410 std::stop_callback __cb(__stoken, [
this] { notify_all(); });
417 if (__stoken.stop_requested())
421 _Unlock<_Lock> __u(__lock);
423 const auto __status = _M_cond.wait_until(__my_lock2, __abs_time);
424 __stop = (__status == std::cv_status::timeout) || __stoken.stop_requested();
434 template <
class _Lock,
class _Rep,
class _Period,
class _Predicate>
435 bool wait_for(_Lock& __lock,
440 auto __abst = std::chrono::steady_clock::now() + __rel_time;
441 return wait_until(__lock,
452 _GLIBCXX_END_NAMESPACE_VERSION
455 #endif // _GLIBCXX_HAS_GTHREADS
457 #endif // _GLIBCXX_CONDITION_VARIABLE