11debfc3dSmrg// <condition_variable> -*- C++ -*- 21debfc3dSmrg 3*8feb0f0bSmrg// Copyright (C) 2008-2020 Free Software Foundation, Inc. 41debfc3dSmrg// 51debfc3dSmrg// This file is part of the GNU ISO C++ Library. This library is free 61debfc3dSmrg// software; you can redistribute it and/or modify it under the 71debfc3dSmrg// terms of the GNU General Public License as published by the 81debfc3dSmrg// Free Software Foundation; either version 3, or (at your option) 91debfc3dSmrg// any later version. 101debfc3dSmrg 111debfc3dSmrg// This library is distributed in the hope that it will be useful, 121debfc3dSmrg// but WITHOUT ANY WARRANTY; without even the implied warranty of 131debfc3dSmrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141debfc3dSmrg// GNU General Public License for more details. 151debfc3dSmrg 161debfc3dSmrg// Under Section 7 of GPL version 3, you are granted additional 171debfc3dSmrg// permissions described in the GCC Runtime Library Exception, version 181debfc3dSmrg// 3.1, as published by the Free Software Foundation. 191debfc3dSmrg 201debfc3dSmrg// You should have received a copy of the GNU General Public License and 211debfc3dSmrg// a copy of the GCC Runtime Library Exception along with this program; 221debfc3dSmrg// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 231debfc3dSmrg// <http://www.gnu.org/licenses/>. 241debfc3dSmrg 251debfc3dSmrg/** @file include/condition_variable 261debfc3dSmrg * This is a Standard C++ Library header. 271debfc3dSmrg */ 281debfc3dSmrg 291debfc3dSmrg#ifndef _GLIBCXX_CONDITION_VARIABLE 301debfc3dSmrg#define _GLIBCXX_CONDITION_VARIABLE 1 311debfc3dSmrg 321debfc3dSmrg#pragma GCC system_header 331debfc3dSmrg 341debfc3dSmrg#if __cplusplus < 201103L 351debfc3dSmrg# include <bits/c++0x_warning.h> 361debfc3dSmrg#else 371debfc3dSmrg 381debfc3dSmrg#include <chrono> 39*8feb0f0bSmrg 401debfc3dSmrg#include <bits/std_mutex.h> 41c0a68be4Smrg#include <bits/unique_lock.h> 421debfc3dSmrg#include <ext/concurrence.h> 431debfc3dSmrg#include <bits/alloc_traits.h> 441debfc3dSmrg#include <bits/allocator.h> 451debfc3dSmrg#include <bits/unique_ptr.h> 461debfc3dSmrg#include <bits/shared_ptr.h> 471debfc3dSmrg#include <bits/cxxabi_forced.h> 481debfc3dSmrg 49*8feb0f0bSmrg#if __cplusplus > 201703L 50*8feb0f0bSmrg# include <stop_token> 51*8feb0f0bSmrg#endif 52*8feb0f0bSmrg 53c0a68be4Smrg#if defined(_GLIBCXX_HAS_GTHREADS) 541debfc3dSmrg 551debfc3dSmrgnamespace std _GLIBCXX_VISIBILITY(default) 561debfc3dSmrg{ 571debfc3dSmrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 581debfc3dSmrg 591debfc3dSmrg /** 601debfc3dSmrg * @defgroup condition_variables Condition Variables 611debfc3dSmrg * @ingroup concurrency 621debfc3dSmrg * 631debfc3dSmrg * Classes for condition_variable support. 641debfc3dSmrg * @{ 651debfc3dSmrg */ 661debfc3dSmrg 671debfc3dSmrg /// cv_status 681debfc3dSmrg enum class cv_status { no_timeout, timeout }; 691debfc3dSmrg 701debfc3dSmrg /// condition_variable 711debfc3dSmrg class condition_variable 721debfc3dSmrg { 73*8feb0f0bSmrg using steady_clock = chrono::steady_clock; 74*8feb0f0bSmrg using system_clock = chrono::system_clock; 75*8feb0f0bSmrg#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT 76*8feb0f0bSmrg using __clock_t = steady_clock; 77*8feb0f0bSmrg#else 78*8feb0f0bSmrg using __clock_t = system_clock; 79*8feb0f0bSmrg#endif 801debfc3dSmrg typedef __gthread_cond_t __native_type; 811debfc3dSmrg 821debfc3dSmrg#ifdef __GTHREAD_COND_INIT 831debfc3dSmrg __native_type _M_cond = __GTHREAD_COND_INIT; 841debfc3dSmrg#else 851debfc3dSmrg __native_type _M_cond; 861debfc3dSmrg#endif 871debfc3dSmrg 881debfc3dSmrg public: 891debfc3dSmrg typedef __native_type* native_handle_type; 901debfc3dSmrg 911debfc3dSmrg condition_variable() noexcept; 921debfc3dSmrg ~condition_variable() noexcept; 931debfc3dSmrg 941debfc3dSmrg condition_variable(const condition_variable&) = delete; 951debfc3dSmrg condition_variable& operator=(const condition_variable&) = delete; 961debfc3dSmrg 971debfc3dSmrg void 981debfc3dSmrg notify_one() noexcept; 991debfc3dSmrg 1001debfc3dSmrg void 1011debfc3dSmrg notify_all() noexcept; 1021debfc3dSmrg 1031debfc3dSmrg void 1041debfc3dSmrg wait(unique_lock<mutex>& __lock) noexcept; 1051debfc3dSmrg 1061debfc3dSmrg template<typename _Predicate> 1071debfc3dSmrg void 1081debfc3dSmrg wait(unique_lock<mutex>& __lock, _Predicate __p) 1091debfc3dSmrg { 1101debfc3dSmrg while (!__p()) 1111debfc3dSmrg wait(__lock); 1121debfc3dSmrg } 1131debfc3dSmrg 114*8feb0f0bSmrg#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT 1151debfc3dSmrg template<typename _Duration> 1161debfc3dSmrg cv_status 1171debfc3dSmrg wait_until(unique_lock<mutex>& __lock, 118*8feb0f0bSmrg const chrono::time_point<steady_clock, _Duration>& __atime) 119*8feb0f0bSmrg { return __wait_until_impl(__lock, __atime); } 120*8feb0f0bSmrg#endif 121*8feb0f0bSmrg 122*8feb0f0bSmrg template<typename _Duration> 123*8feb0f0bSmrg cv_status 124*8feb0f0bSmrg wait_until(unique_lock<mutex>& __lock, 125*8feb0f0bSmrg const chrono::time_point<system_clock, _Duration>& __atime) 1261debfc3dSmrg { return __wait_until_impl(__lock, __atime); } 1271debfc3dSmrg 1281debfc3dSmrg template<typename _Clock, typename _Duration> 1291debfc3dSmrg cv_status 1301debfc3dSmrg wait_until(unique_lock<mutex>& __lock, 1311debfc3dSmrg const chrono::time_point<_Clock, _Duration>& __atime) 1321debfc3dSmrg { 133*8feb0f0bSmrg#if __cplusplus > 201703L 134*8feb0f0bSmrg static_assert(chrono::is_clock_v<_Clock>); 135*8feb0f0bSmrg#endif 1361debfc3dSmrg const typename _Clock::time_point __c_entry = _Clock::now(); 1371debfc3dSmrg const __clock_t::time_point __s_entry = __clock_t::now(); 1381debfc3dSmrg const auto __delta = __atime - __c_entry; 1391debfc3dSmrg const auto __s_atime = __s_entry + __delta; 1401debfc3dSmrg 141c0a68be4Smrg if (__wait_until_impl(__lock, __s_atime) == cv_status::no_timeout) 142c0a68be4Smrg return cv_status::no_timeout; 143c0a68be4Smrg // We got a timeout when measured against __clock_t but 144c0a68be4Smrg // we need to check against the caller-supplied clock 145c0a68be4Smrg // to tell whether we should return a timeout. 146c0a68be4Smrg if (_Clock::now() < __atime) 147c0a68be4Smrg return cv_status::no_timeout; 148c0a68be4Smrg return cv_status::timeout; 1491debfc3dSmrg } 1501debfc3dSmrg 1511debfc3dSmrg template<typename _Clock, typename _Duration, typename _Predicate> 1521debfc3dSmrg bool 1531debfc3dSmrg wait_until(unique_lock<mutex>& __lock, 1541debfc3dSmrg const chrono::time_point<_Clock, _Duration>& __atime, 1551debfc3dSmrg _Predicate __p) 1561debfc3dSmrg { 1571debfc3dSmrg while (!__p()) 1581debfc3dSmrg if (wait_until(__lock, __atime) == cv_status::timeout) 1591debfc3dSmrg return __p(); 1601debfc3dSmrg return true; 1611debfc3dSmrg } 1621debfc3dSmrg 1631debfc3dSmrg template<typename _Rep, typename _Period> 1641debfc3dSmrg cv_status 1651debfc3dSmrg wait_for(unique_lock<mutex>& __lock, 1661debfc3dSmrg const chrono::duration<_Rep, _Period>& __rtime) 1671debfc3dSmrg { 168*8feb0f0bSmrg using __dur = typename steady_clock::duration; 1691debfc3dSmrg auto __reltime = chrono::duration_cast<__dur>(__rtime); 1701debfc3dSmrg if (__reltime < __rtime) 1711debfc3dSmrg ++__reltime; 172*8feb0f0bSmrg return wait_until(__lock, steady_clock::now() + __reltime); 1731debfc3dSmrg } 1741debfc3dSmrg 1751debfc3dSmrg template<typename _Rep, typename _Period, typename _Predicate> 1761debfc3dSmrg bool 1771debfc3dSmrg wait_for(unique_lock<mutex>& __lock, 1781debfc3dSmrg const chrono::duration<_Rep, _Period>& __rtime, 1791debfc3dSmrg _Predicate __p) 1801debfc3dSmrg { 181*8feb0f0bSmrg using __dur = typename steady_clock::duration; 1821debfc3dSmrg auto __reltime = chrono::duration_cast<__dur>(__rtime); 1831debfc3dSmrg if (__reltime < __rtime) 1841debfc3dSmrg ++__reltime; 185*8feb0f0bSmrg return wait_until(__lock, steady_clock::now() + __reltime, 186c0a68be4Smrg std::move(__p)); 1871debfc3dSmrg } 1881debfc3dSmrg 1891debfc3dSmrg native_handle_type 1901debfc3dSmrg native_handle() 1911debfc3dSmrg { return &_M_cond; } 1921debfc3dSmrg 1931debfc3dSmrg private: 194*8feb0f0bSmrg#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT 1951debfc3dSmrg template<typename _Dur> 1961debfc3dSmrg cv_status 1971debfc3dSmrg __wait_until_impl(unique_lock<mutex>& __lock, 198*8feb0f0bSmrg const chrono::time_point<steady_clock, _Dur>& __atime) 199*8feb0f0bSmrg { 200*8feb0f0bSmrg auto __s = chrono::time_point_cast<chrono::seconds>(__atime); 201*8feb0f0bSmrg auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); 202*8feb0f0bSmrg 203*8feb0f0bSmrg __gthread_time_t __ts = 204*8feb0f0bSmrg { 205*8feb0f0bSmrg static_cast<std::time_t>(__s.time_since_epoch().count()), 206*8feb0f0bSmrg static_cast<long>(__ns.count()) 207*8feb0f0bSmrg }; 208*8feb0f0bSmrg 209*8feb0f0bSmrg pthread_cond_clockwait(&_M_cond, __lock.mutex()->native_handle(), 210*8feb0f0bSmrg CLOCK_MONOTONIC, 211*8feb0f0bSmrg &__ts); 212*8feb0f0bSmrg 213*8feb0f0bSmrg return (steady_clock::now() < __atime 214*8feb0f0bSmrg ? cv_status::no_timeout : cv_status::timeout); 215*8feb0f0bSmrg } 216*8feb0f0bSmrg#endif 217*8feb0f0bSmrg 218*8feb0f0bSmrg template<typename _Dur> 219*8feb0f0bSmrg cv_status 220*8feb0f0bSmrg __wait_until_impl(unique_lock<mutex>& __lock, 221*8feb0f0bSmrg const chrono::time_point<system_clock, _Dur>& __atime) 2221debfc3dSmrg { 2231debfc3dSmrg auto __s = chrono::time_point_cast<chrono::seconds>(__atime); 2241debfc3dSmrg auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); 2251debfc3dSmrg 2261debfc3dSmrg __gthread_time_t __ts = 2271debfc3dSmrg { 2281debfc3dSmrg static_cast<std::time_t>(__s.time_since_epoch().count()), 2291debfc3dSmrg static_cast<long>(__ns.count()) 2301debfc3dSmrg }; 2311debfc3dSmrg 2321debfc3dSmrg __gthread_cond_timedwait(&_M_cond, __lock.mutex()->native_handle(), 2331debfc3dSmrg &__ts); 2341debfc3dSmrg 235*8feb0f0bSmrg return (system_clock::now() < __atime 2361debfc3dSmrg ? cv_status::no_timeout : cv_status::timeout); 2371debfc3dSmrg } 2381debfc3dSmrg }; 2391debfc3dSmrg 2401debfc3dSmrg void 2411debfc3dSmrg notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>); 2421debfc3dSmrg 2431debfc3dSmrg struct __at_thread_exit_elt 2441debfc3dSmrg { 2451debfc3dSmrg __at_thread_exit_elt* _M_next; 2461debfc3dSmrg void (*_M_cb)(void*); 2471debfc3dSmrg }; 2481debfc3dSmrg 2491debfc3dSmrg inline namespace _V2 { 2501debfc3dSmrg 2511debfc3dSmrg /// condition_variable_any 2521debfc3dSmrg // Like above, but mutex is not required to have try_lock. 2531debfc3dSmrg class condition_variable_any 2541debfc3dSmrg { 255*8feb0f0bSmrg#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT 256*8feb0f0bSmrg using __clock_t = chrono::steady_clock; 257*8feb0f0bSmrg#else 258*8feb0f0bSmrg using __clock_t = chrono::system_clock; 259*8feb0f0bSmrg#endif 2601debfc3dSmrg condition_variable _M_cond; 2611debfc3dSmrg shared_ptr<mutex> _M_mutex; 2621debfc3dSmrg 2631debfc3dSmrg // scoped unlock - unlocks in ctor, re-locks in dtor 2641debfc3dSmrg template<typename _Lock> 2651debfc3dSmrg struct _Unlock 2661debfc3dSmrg { 2671debfc3dSmrg explicit _Unlock(_Lock& __lk) : _M_lock(__lk) { __lk.unlock(); } 2681debfc3dSmrg 269*8feb0f0bSmrg#pragma GCC diagnostic push 270*8feb0f0bSmrg#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 2711debfc3dSmrg ~_Unlock() noexcept(false) 2721debfc3dSmrg { 2731debfc3dSmrg if (uncaught_exception()) 2741debfc3dSmrg { 2751debfc3dSmrg __try 2761debfc3dSmrg { _M_lock.lock(); } 2771debfc3dSmrg __catch(const __cxxabiv1::__forced_unwind&) 2781debfc3dSmrg { __throw_exception_again; } 2791debfc3dSmrg __catch(...) 2801debfc3dSmrg { } 2811debfc3dSmrg } 2821debfc3dSmrg else 2831debfc3dSmrg _M_lock.lock(); 2841debfc3dSmrg } 285*8feb0f0bSmrg#pragma GCC diagnostic pop 2861debfc3dSmrg 2871debfc3dSmrg _Unlock(const _Unlock&) = delete; 2881debfc3dSmrg _Unlock& operator=(const _Unlock&) = delete; 2891debfc3dSmrg 2901debfc3dSmrg _Lock& _M_lock; 2911debfc3dSmrg }; 2921debfc3dSmrg 2931debfc3dSmrg public: 2941debfc3dSmrg condition_variable_any() : _M_mutex(std::make_shared<mutex>()) { } 2951debfc3dSmrg ~condition_variable_any() = default; 2961debfc3dSmrg 2971debfc3dSmrg condition_variable_any(const condition_variable_any&) = delete; 2981debfc3dSmrg condition_variable_any& operator=(const condition_variable_any&) = delete; 2991debfc3dSmrg 3001debfc3dSmrg void 3011debfc3dSmrg notify_one() noexcept 3021debfc3dSmrg { 3031debfc3dSmrg lock_guard<mutex> __lock(*_M_mutex); 3041debfc3dSmrg _M_cond.notify_one(); 3051debfc3dSmrg } 3061debfc3dSmrg 3071debfc3dSmrg void 3081debfc3dSmrg notify_all() noexcept 3091debfc3dSmrg { 3101debfc3dSmrg lock_guard<mutex> __lock(*_M_mutex); 3111debfc3dSmrg _M_cond.notify_all(); 3121debfc3dSmrg } 3131debfc3dSmrg 3141debfc3dSmrg template<typename _Lock> 3151debfc3dSmrg void 3161debfc3dSmrg wait(_Lock& __lock) 3171debfc3dSmrg { 3181debfc3dSmrg shared_ptr<mutex> __mutex = _M_mutex; 3191debfc3dSmrg unique_lock<mutex> __my_lock(*__mutex); 3201debfc3dSmrg _Unlock<_Lock> __unlock(__lock); 3211debfc3dSmrg // *__mutex must be unlocked before re-locking __lock so move 3221debfc3dSmrg // ownership of *__mutex lock to an object with shorter lifetime. 3231debfc3dSmrg unique_lock<mutex> __my_lock2(std::move(__my_lock)); 3241debfc3dSmrg _M_cond.wait(__my_lock2); 3251debfc3dSmrg } 3261debfc3dSmrg 3271debfc3dSmrg 3281debfc3dSmrg template<typename _Lock, typename _Predicate> 3291debfc3dSmrg void 3301debfc3dSmrg wait(_Lock& __lock, _Predicate __p) 3311debfc3dSmrg { 3321debfc3dSmrg while (!__p()) 3331debfc3dSmrg wait(__lock); 3341debfc3dSmrg } 3351debfc3dSmrg 3361debfc3dSmrg template<typename _Lock, typename _Clock, typename _Duration> 3371debfc3dSmrg cv_status 3381debfc3dSmrg wait_until(_Lock& __lock, 3391debfc3dSmrg const chrono::time_point<_Clock, _Duration>& __atime) 3401debfc3dSmrg { 3411debfc3dSmrg shared_ptr<mutex> __mutex = _M_mutex; 3421debfc3dSmrg unique_lock<mutex> __my_lock(*__mutex); 3431debfc3dSmrg _Unlock<_Lock> __unlock(__lock); 3441debfc3dSmrg // *__mutex must be unlocked before re-locking __lock so move 3451debfc3dSmrg // ownership of *__mutex lock to an object with shorter lifetime. 3461debfc3dSmrg unique_lock<mutex> __my_lock2(std::move(__my_lock)); 3471debfc3dSmrg return _M_cond.wait_until(__my_lock2, __atime); 3481debfc3dSmrg } 3491debfc3dSmrg 3501debfc3dSmrg template<typename _Lock, typename _Clock, 3511debfc3dSmrg typename _Duration, typename _Predicate> 3521debfc3dSmrg bool 3531debfc3dSmrg wait_until(_Lock& __lock, 3541debfc3dSmrg const chrono::time_point<_Clock, _Duration>& __atime, 3551debfc3dSmrg _Predicate __p) 3561debfc3dSmrg { 3571debfc3dSmrg while (!__p()) 3581debfc3dSmrg if (wait_until(__lock, __atime) == cv_status::timeout) 3591debfc3dSmrg return __p(); 3601debfc3dSmrg return true; 3611debfc3dSmrg } 3621debfc3dSmrg 3631debfc3dSmrg template<typename _Lock, typename _Rep, typename _Period> 3641debfc3dSmrg cv_status 3651debfc3dSmrg wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __rtime) 3661debfc3dSmrg { return wait_until(__lock, __clock_t::now() + __rtime); } 3671debfc3dSmrg 3681debfc3dSmrg template<typename _Lock, typename _Rep, 3691debfc3dSmrg typename _Period, typename _Predicate> 3701debfc3dSmrg bool 3711debfc3dSmrg wait_for(_Lock& __lock, 3721debfc3dSmrg const chrono::duration<_Rep, _Period>& __rtime, _Predicate __p) 3731debfc3dSmrg { return wait_until(__lock, __clock_t::now() + __rtime, std::move(__p)); } 374*8feb0f0bSmrg 375*8feb0f0bSmrg#ifdef __cpp_lib_jthread 376*8feb0f0bSmrg template <class _Lock, class _Predicate> 377*8feb0f0bSmrg bool wait(_Lock& __lock, 378*8feb0f0bSmrg stop_token __stoken, 379*8feb0f0bSmrg _Predicate __p) 380*8feb0f0bSmrg { 381*8feb0f0bSmrg if (__stoken.stop_requested()) 382*8feb0f0bSmrg { 383*8feb0f0bSmrg return __p(); 384*8feb0f0bSmrg } 385*8feb0f0bSmrg 386*8feb0f0bSmrg std::stop_callback __cb(__stoken, [this] { notify_all(); }); 387*8feb0f0bSmrg shared_ptr<mutex> __mutex = _M_mutex; 388*8feb0f0bSmrg while (!__p()) 389*8feb0f0bSmrg { 390*8feb0f0bSmrg unique_lock<mutex> __my_lock(*__mutex); 391*8feb0f0bSmrg if (__stoken.stop_requested()) 392*8feb0f0bSmrg { 393*8feb0f0bSmrg return false; 394*8feb0f0bSmrg } 395*8feb0f0bSmrg // *__mutex must be unlocked before re-locking __lock so move 396*8feb0f0bSmrg // ownership of *__mutex lock to an object with shorter lifetime. 397*8feb0f0bSmrg _Unlock<_Lock> __unlock(__lock); 398*8feb0f0bSmrg unique_lock<mutex> __my_lock2(std::move(__my_lock)); 399*8feb0f0bSmrg _M_cond.wait(__my_lock2); 400*8feb0f0bSmrg } 401*8feb0f0bSmrg return true; 402*8feb0f0bSmrg } 403*8feb0f0bSmrg 404*8feb0f0bSmrg template <class _Lock, class _Clock, class _Duration, class _Predicate> 405*8feb0f0bSmrg bool wait_until(_Lock& __lock, 406*8feb0f0bSmrg stop_token __stoken, 407*8feb0f0bSmrg const chrono::time_point<_Clock, _Duration>& __abs_time, 408*8feb0f0bSmrg _Predicate __p) 409*8feb0f0bSmrg { 410*8feb0f0bSmrg if (__stoken.stop_requested()) 411*8feb0f0bSmrg { 412*8feb0f0bSmrg return __p(); 413*8feb0f0bSmrg } 414*8feb0f0bSmrg 415*8feb0f0bSmrg std::stop_callback __cb(__stoken, [this] { notify_all(); }); 416*8feb0f0bSmrg shared_ptr<mutex> __mutex = _M_mutex; 417*8feb0f0bSmrg while (!__p()) 418*8feb0f0bSmrg { 419*8feb0f0bSmrg bool __stop; 420*8feb0f0bSmrg { 421*8feb0f0bSmrg unique_lock<mutex> __my_lock(*__mutex); 422*8feb0f0bSmrg if (__stoken.stop_requested()) 423*8feb0f0bSmrg { 424*8feb0f0bSmrg return false; 425*8feb0f0bSmrg } 426*8feb0f0bSmrg _Unlock<_Lock> __u(__lock); 427*8feb0f0bSmrg unique_lock<mutex> __my_lock2(std::move(__my_lock)); 428*8feb0f0bSmrg const auto __status = _M_cond.wait_until(__my_lock2, __abs_time); 429*8feb0f0bSmrg __stop = (__status == std::cv_status::timeout) || __stoken.stop_requested(); 430*8feb0f0bSmrg } 431*8feb0f0bSmrg if (__stop) 432*8feb0f0bSmrg { 433*8feb0f0bSmrg return __p(); 434*8feb0f0bSmrg } 435*8feb0f0bSmrg } 436*8feb0f0bSmrg return true; 437*8feb0f0bSmrg } 438*8feb0f0bSmrg 439*8feb0f0bSmrg template <class _Lock, class _Rep, class _Period, class _Predicate> 440*8feb0f0bSmrg bool wait_for(_Lock& __lock, 441*8feb0f0bSmrg stop_token __stoken, 442*8feb0f0bSmrg const chrono::duration<_Rep, _Period>& __rel_time, 443*8feb0f0bSmrg _Predicate __p) 444*8feb0f0bSmrg { 445*8feb0f0bSmrg auto __abst = std::chrono::steady_clock::now() + __rel_time; 446*8feb0f0bSmrg return wait_until(__lock, 447*8feb0f0bSmrg std::move(__stoken), 448*8feb0f0bSmrg __abst, 449*8feb0f0bSmrg std::move(__p)); 450*8feb0f0bSmrg } 451*8feb0f0bSmrg#endif 4521debfc3dSmrg }; 4531debfc3dSmrg 4541debfc3dSmrg } // end inline namespace 4551debfc3dSmrg 456*8feb0f0bSmrg /// @} group condition_variables 4571debfc3dSmrg_GLIBCXX_END_NAMESPACE_VERSION 4581debfc3dSmrg} // namespace 4591debfc3dSmrg 460c0a68be4Smrg#endif // _GLIBCXX_HAS_GTHREADS 4611debfc3dSmrg#endif // C++11 4621debfc3dSmrg#endif // _GLIBCXX_CONDITION_VARIABLE 463