xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/std/condition_variable (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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