xref: /llvm-project/libcxx/include/__cxx03/condition_variable (revision ce7771902dc50d900de639d499a60486b83f70e0)
1e78f53d1SNikolas Klauser// -*- C++ -*-
2e78f53d1SNikolas Klauser//===----------------------------------------------------------------------===//
3e78f53d1SNikolas Klauser//
4e78f53d1SNikolas Klauser// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5e78f53d1SNikolas Klauser// See https://llvm.org/LICENSE.txt for license information.
6e78f53d1SNikolas Klauser// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7e78f53d1SNikolas Klauser//
8e78f53d1SNikolas Klauser//===----------------------------------------------------------------------===//
9e78f53d1SNikolas Klauser
10*ce777190SNikolas Klauser#ifndef _LIBCPP___CXX03_CONDITION_VARIABLE
11*ce777190SNikolas Klauser#define _LIBCPP___CXX03_CONDITION_VARIABLE
12e78f53d1SNikolas Klauser
13e78f53d1SNikolas Klauser/*
14e78f53d1SNikolas Klauser    condition_variable synopsis
15e78f53d1SNikolas Klauser
16e78f53d1SNikolas Klausernamespace std
17e78f53d1SNikolas Klauser{
18e78f53d1SNikolas Klauser
19e78f53d1SNikolas Klauserenum class cv_status { no_timeout, timeout };
20e78f53d1SNikolas Klauser
21e78f53d1SNikolas Klauserclass condition_variable
22e78f53d1SNikolas Klauser{
23e78f53d1SNikolas Klauserpublic:
24e78f53d1SNikolas Klauser    condition_variable();
25e78f53d1SNikolas Klauser    ~condition_variable();
26e78f53d1SNikolas Klauser
27e78f53d1SNikolas Klauser    condition_variable(const condition_variable&) = delete;
28e78f53d1SNikolas Klauser    condition_variable& operator=(const condition_variable&) = delete;
29e78f53d1SNikolas Klauser
30e78f53d1SNikolas Klauser    void notify_one() noexcept;
31e78f53d1SNikolas Klauser    void notify_all() noexcept;
32e78f53d1SNikolas Klauser
33e78f53d1SNikolas Klauser    void wait(unique_lock<mutex>& lock);
34e78f53d1SNikolas Klauser    template <class Predicate>
35e78f53d1SNikolas Klauser        void wait(unique_lock<mutex>& lock, Predicate pred);
36e78f53d1SNikolas Klauser
37e78f53d1SNikolas Klauser    template <class Clock, class Duration>
38e78f53d1SNikolas Klauser        cv_status
39e78f53d1SNikolas Klauser        wait_until(unique_lock<mutex>& lock,
40e78f53d1SNikolas Klauser                   const chrono::time_point<Clock, Duration>& abs_time);
41e78f53d1SNikolas Klauser
42e78f53d1SNikolas Klauser    template <class Clock, class Duration, class Predicate>
43e78f53d1SNikolas Klauser        bool
44e78f53d1SNikolas Klauser        wait_until(unique_lock<mutex>& lock,
45e78f53d1SNikolas Klauser                   const chrono::time_point<Clock, Duration>& abs_time,
46e78f53d1SNikolas Klauser                   Predicate pred);
47e78f53d1SNikolas Klauser
48e78f53d1SNikolas Klauser    template <class Rep, class Period>
49e78f53d1SNikolas Klauser        cv_status
50e78f53d1SNikolas Klauser        wait_for(unique_lock<mutex>& lock,
51e78f53d1SNikolas Klauser                 const chrono::duration<Rep, Period>& rel_time);
52e78f53d1SNikolas Klauser
53e78f53d1SNikolas Klauser    template <class Rep, class Period, class Predicate>
54e78f53d1SNikolas Klauser        bool
55e78f53d1SNikolas Klauser        wait_for(unique_lock<mutex>& lock,
56e78f53d1SNikolas Klauser                 const chrono::duration<Rep, Period>& rel_time,
57e78f53d1SNikolas Klauser                 Predicate pred);
58e78f53d1SNikolas Klauser
59e78f53d1SNikolas Klauser    typedef pthread_cond_t* native_handle_type;
60e78f53d1SNikolas Klauser    native_handle_type native_handle();
61e78f53d1SNikolas Klauser};
62e78f53d1SNikolas Klauser
63e78f53d1SNikolas Klauservoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
64e78f53d1SNikolas Klauser
65e78f53d1SNikolas Klauserclass condition_variable_any
66e78f53d1SNikolas Klauser{
67e78f53d1SNikolas Klauserpublic:
68e78f53d1SNikolas Klauser    condition_variable_any();
69e78f53d1SNikolas Klauser    ~condition_variable_any();
70e78f53d1SNikolas Klauser
71e78f53d1SNikolas Klauser    condition_variable_any(const condition_variable_any&) = delete;
72e78f53d1SNikolas Klauser    condition_variable_any& operator=(const condition_variable_any&) = delete;
73e78f53d1SNikolas Klauser
74e78f53d1SNikolas Klauser    void notify_one() noexcept;
75e78f53d1SNikolas Klauser    void notify_all() noexcept;
76e78f53d1SNikolas Klauser
77e78f53d1SNikolas Klauser    template <class Lock>
78e78f53d1SNikolas Klauser        void wait(Lock& lock);
79e78f53d1SNikolas Klauser    template <class Lock, class Predicate>
80e78f53d1SNikolas Klauser        void wait(Lock& lock, Predicate pred);
81e78f53d1SNikolas Klauser
82e78f53d1SNikolas Klauser    template <class Lock, class Clock, class Duration>
83e78f53d1SNikolas Klauser        cv_status
84e78f53d1SNikolas Klauser        wait_until(Lock& lock,
85e78f53d1SNikolas Klauser                   const chrono::time_point<Clock, Duration>& abs_time);
86e78f53d1SNikolas Klauser
87e78f53d1SNikolas Klauser    template <class Lock, class Clock, class Duration, class Predicate>
88e78f53d1SNikolas Klauser        bool
89e78f53d1SNikolas Klauser        wait_until(Lock& lock,
90e78f53d1SNikolas Klauser                   const chrono::time_point<Clock, Duration>& abs_time,
91e78f53d1SNikolas Klauser                   Predicate pred);
92e78f53d1SNikolas Klauser
93e78f53d1SNikolas Klauser    template <class Lock, class Rep, class Period>
94e78f53d1SNikolas Klauser        cv_status
95e78f53d1SNikolas Klauser        wait_for(Lock& lock,
96e78f53d1SNikolas Klauser                 const chrono::duration<Rep, Period>& rel_time);
97e78f53d1SNikolas Klauser
98e78f53d1SNikolas Klauser    template <class Lock, class Rep, class Period, class Predicate>
99e78f53d1SNikolas Klauser        bool
100e78f53d1SNikolas Klauser        wait_for(Lock& lock,
101e78f53d1SNikolas Klauser                 const chrono::duration<Rep, Period>& rel_time,
102e78f53d1SNikolas Klauser                 Predicate pred);
103e78f53d1SNikolas Klauser
104e78f53d1SNikolas Klauser    // [thread.condvarany.intwait], interruptible waits
105e78f53d1SNikolas Klauser    template <class Lock, class Predicate>
106e78f53d1SNikolas Klauser      bool wait(Lock& lock, stop_token stoken, Predicate pred);                               // since C++20
107e78f53d1SNikolas Klauser
108e78f53d1SNikolas Klauser    template <class Lock, class Clock, class Duration, class Predicate>
109e78f53d1SNikolas Klauser      bool wait_until(Lock& lock, stop_token stoken,
110e78f53d1SNikolas Klauser                      const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);   // since C++20
111e78f53d1SNikolas Klauser
112e78f53d1SNikolas Klauser    template <class Lock, class Rep, class Period, class Predicate>
113e78f53d1SNikolas Klauser      bool wait_for(Lock& lock, stop_token stoken,
114e78f53d1SNikolas Klauser                    const chrono::duration<Rep, Period>& rel_time, Predicate pred);           // since C++20
115e78f53d1SNikolas Klauser};
116e78f53d1SNikolas Klauser
117e78f53d1SNikolas Klauser}  // std
118e78f53d1SNikolas Klauser
119e78f53d1SNikolas Klauser*/
120e78f53d1SNikolas Klauser
12173fbae83SNikolas Klauser#include <__cxx03/__chrono/duration.h>
12273fbae83SNikolas Klauser#include <__cxx03/__chrono/steady_clock.h>
12373fbae83SNikolas Klauser#include <__cxx03/__chrono/time_point.h>
12473fbae83SNikolas Klauser#include <__cxx03/__condition_variable/condition_variable.h>
12573fbae83SNikolas Klauser#include <__cxx03/__config>
12673fbae83SNikolas Klauser#include <__cxx03/__memory/shared_ptr.h>
12773fbae83SNikolas Klauser#include <__cxx03/__mutex/lock_guard.h>
12873fbae83SNikolas Klauser#include <__cxx03/__mutex/mutex.h>
12973fbae83SNikolas Klauser#include <__cxx03/__mutex/tag_types.h>
13073fbae83SNikolas Klauser#include <__cxx03/__mutex/unique_lock.h>
13173fbae83SNikolas Klauser#include <__cxx03/__stop_token/stop_callback.h>
13273fbae83SNikolas Klauser#include <__cxx03/__stop_token/stop_token.h>
13373fbae83SNikolas Klauser#include <__cxx03/__utility/move.h>
13473fbae83SNikolas Klauser#include <__cxx03/version>
135e78f53d1SNikolas Klauser
136e78f53d1SNikolas Klauser#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
137e78f53d1SNikolas Klauser#  pragma GCC system_header
138e78f53d1SNikolas Klauser#endif
139e78f53d1SNikolas Klauser
140e78f53d1SNikolas Klauser_LIBCPP_PUSH_MACROS
14173fbae83SNikolas Klauser#include <__cxx03/__undef_macros>
142e78f53d1SNikolas Klauser
143e78f53d1SNikolas Klauser#ifndef _LIBCPP_HAS_NO_THREADS
144e78f53d1SNikolas Klauser
145e78f53d1SNikolas Klauser_LIBCPP_BEGIN_NAMESPACE_STD
146e78f53d1SNikolas Klauser
147e78f53d1SNikolas Klauserclass _LIBCPP_EXPORTED_FROM_ABI condition_variable_any {
148e78f53d1SNikolas Klauser  condition_variable __cv_;
149e78f53d1SNikolas Klauser  shared_ptr<mutex> __mut_;
150e78f53d1SNikolas Klauser
151e78f53d1SNikolas Klauserpublic:
152e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI condition_variable_any();
153e78f53d1SNikolas Klauser
154e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT;
155e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT;
156e78f53d1SNikolas Klauser
157e78f53d1SNikolas Klauser  template <class _Lock>
158e78f53d1SNikolas Klauser  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS void wait(_Lock& __lock);
159e78f53d1SNikolas Klauser  template <class _Lock, class _Predicate>
160e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI void wait(_Lock& __lock, _Predicate __pred);
161e78f53d1SNikolas Klauser
162e78f53d1SNikolas Klauser  template <class _Lock, class _Clock, class _Duration>
163e78f53d1SNikolas Klauser  _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status
164e78f53d1SNikolas Klauser  wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t);
165e78f53d1SNikolas Klauser
166e78f53d1SNikolas Klauser  template <class _Lock, class _Clock, class _Duration, class _Predicate>
167e78f53d1SNikolas Klauser  bool _LIBCPP_HIDE_FROM_ABI
168e78f53d1SNikolas Klauser  wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred);
169e78f53d1SNikolas Klauser
170e78f53d1SNikolas Klauser  template <class _Lock, class _Rep, class _Period>
171e78f53d1SNikolas Klauser  cv_status _LIBCPP_HIDE_FROM_ABI wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __d);
172e78f53d1SNikolas Klauser
173e78f53d1SNikolas Klauser  template <class _Lock, class _Rep, class _Period, class _Predicate>
174e78f53d1SNikolas Klauser  bool _LIBCPP_HIDE_FROM_ABI wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred);
175e78f53d1SNikolas Klauser
176e78f53d1SNikolas Klauser#  if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
177e78f53d1SNikolas Klauser
178e78f53d1SNikolas Klauser  template <class _Lock, class _Predicate>
179e78f53d1SNikolas Klauser  _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait(_Lock& __lock, stop_token __stoken, _Predicate __pred);
180e78f53d1SNikolas Klauser
181e78f53d1SNikolas Klauser  template <class _Lock, class _Clock, class _Duration, class _Predicate>
182e78f53d1SNikolas Klauser  _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait_until(
183e78f53d1SNikolas Klauser      _Lock& __lock, stop_token __stoken, const chrono::time_point<_Clock, _Duration>& __abs_time, _Predicate __pred);
184e78f53d1SNikolas Klauser
185e78f53d1SNikolas Klauser  template <class _Lock, class _Rep, class _Period, class _Predicate>
186e78f53d1SNikolas Klauser  _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool
187e78f53d1SNikolas Klauser  wait_for(_Lock& __lock, stop_token __stoken, const chrono::duration<_Rep, _Period>& __rel_time, _Predicate __pred);
188e78f53d1SNikolas Klauser
189e78f53d1SNikolas Klauser#  endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
190e78f53d1SNikolas Klauser};
191e78f53d1SNikolas Klauser
192e78f53d1SNikolas Klauserinline condition_variable_any::condition_variable_any() : __mut_(make_shared<mutex>()) {}
193e78f53d1SNikolas Klauser
194e78f53d1SNikolas Klauserinline void condition_variable_any::notify_one() _NOEXCEPT {
195e78f53d1SNikolas Klauser  { lock_guard<mutex> __lx(*__mut_); }
196e78f53d1SNikolas Klauser  __cv_.notify_one();
197e78f53d1SNikolas Klauser}
198e78f53d1SNikolas Klauser
199e78f53d1SNikolas Klauserinline void condition_variable_any::notify_all() _NOEXCEPT {
200e78f53d1SNikolas Klauser  { lock_guard<mutex> __lx(*__mut_); }
201e78f53d1SNikolas Klauser  __cv_.notify_all();
202e78f53d1SNikolas Klauser}
203e78f53d1SNikolas Klauser
204e78f53d1SNikolas Klausertemplate <class _Lock>
205e78f53d1SNikolas Klauserstruct __unlock_guard {
206e78f53d1SNikolas Klauser  _Lock& __lock_;
207e78f53d1SNikolas Klauser
208e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI __unlock_guard(_Lock& __lock) : __lock_(__lock) { __lock_.unlock(); }
209e78f53d1SNikolas Klauser
210e78f53d1SNikolas Klauser  _LIBCPP_HIDE_FROM_ABI ~__unlock_guard() _NOEXCEPT // turns exception to std::terminate
211e78f53d1SNikolas Klauser  {
212e78f53d1SNikolas Klauser    __lock_.lock();
213e78f53d1SNikolas Klauser  }
214e78f53d1SNikolas Klauser
215e78f53d1SNikolas Klauser  __unlock_guard(const __unlock_guard&)            = delete;
216e78f53d1SNikolas Klauser  __unlock_guard& operator=(const __unlock_guard&) = delete;
217e78f53d1SNikolas Klauser};
218e78f53d1SNikolas Klauser
219e78f53d1SNikolas Klausertemplate <class _Lock>
220e78f53d1SNikolas Klauservoid condition_variable_any::wait(_Lock& __lock) {
221e78f53d1SNikolas Klauser  shared_ptr<mutex> __mut = __mut_;
222e78f53d1SNikolas Klauser  unique_lock<mutex> __lk(*__mut);
223e78f53d1SNikolas Klauser  __unlock_guard<_Lock> __unlock(__lock);
224e78f53d1SNikolas Klauser  lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t());
225e78f53d1SNikolas Klauser  __cv_.wait(__lk);
226e78f53d1SNikolas Klauser} // __mut_.unlock(), __lock.lock()
227e78f53d1SNikolas Klauser
228e78f53d1SNikolas Klausertemplate <class _Lock, class _Predicate>
229e78f53d1SNikolas Klauserinline void condition_variable_any::wait(_Lock& __lock, _Predicate __pred) {
230e78f53d1SNikolas Klauser  while (!__pred())
231e78f53d1SNikolas Klauser    wait(__lock);
232e78f53d1SNikolas Klauser}
233e78f53d1SNikolas Klauser
234e78f53d1SNikolas Klausertemplate <class _Lock, class _Clock, class _Duration>
235e78f53d1SNikolas Klausercv_status condition_variable_any::wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t) {
236e78f53d1SNikolas Klauser  shared_ptr<mutex> __mut = __mut_;
237e78f53d1SNikolas Klauser  unique_lock<mutex> __lk(*__mut);
238e78f53d1SNikolas Klauser  __unlock_guard<_Lock> __unlock(__lock);
239e78f53d1SNikolas Klauser  lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t());
240e78f53d1SNikolas Klauser  return __cv_.wait_until(__lk, __t);
241e78f53d1SNikolas Klauser} // __mut_.unlock(), __lock.lock()
242e78f53d1SNikolas Klauser
243e78f53d1SNikolas Klausertemplate <class _Lock, class _Clock, class _Duration, class _Predicate>
244e78f53d1SNikolas Klauserinline bool
245e78f53d1SNikolas Klausercondition_variable_any::wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) {
246e78f53d1SNikolas Klauser  while (!__pred())
247e78f53d1SNikolas Klauser    if (wait_until(__lock, __t) == cv_status::timeout)
248e78f53d1SNikolas Klauser      return __pred();
249e78f53d1SNikolas Klauser  return true;
250e78f53d1SNikolas Klauser}
251e78f53d1SNikolas Klauser
252e78f53d1SNikolas Klausertemplate <class _Lock, class _Rep, class _Period>
253e78f53d1SNikolas Klauserinline cv_status condition_variable_any::wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __d) {
254e78f53d1SNikolas Klauser  return wait_until(__lock, chrono::steady_clock::now() + __d);
255e78f53d1SNikolas Klauser}
256e78f53d1SNikolas Klauser
257e78f53d1SNikolas Klausertemplate <class _Lock, class _Rep, class _Period, class _Predicate>
258e78f53d1SNikolas Klauserinline bool
259e78f53d1SNikolas Klausercondition_variable_any::wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred) {
260e78f53d1SNikolas Klauser  return wait_until(__lock, chrono::steady_clock::now() + __d, std::move(__pred));
261e78f53d1SNikolas Klauser}
262e78f53d1SNikolas Klauser
263e78f53d1SNikolas Klauser#  if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
264e78f53d1SNikolas Klauser
265e78f53d1SNikolas Klausertemplate <class _Lock, class _Predicate>
266e78f53d1SNikolas Klauserbool condition_variable_any::wait(_Lock& __user_lock, stop_token __stoken, _Predicate __pred) {
267e78f53d1SNikolas Klauser  if (__stoken.stop_requested())
268e78f53d1SNikolas Klauser    return __pred();
269e78f53d1SNikolas Klauser
270e78f53d1SNikolas Klauser  // Per https://eel.is/c++draft/thread.condition.condvarany#general-note-2,
271e78f53d1SNikolas Klauser  // we do need to take a copy of the shared pointer __mut_
272e78f53d1SNikolas Klauser  // This ensures that a thread can call the destructor immediately after calling
273e78f53d1SNikolas Klauser  // notify_all, without waiting all the wait calls.
274e78f53d1SNikolas Klauser  // A thread can also safely call the destructor immediately after calling
275e78f53d1SNikolas Klauser  // request_stop, as the call to request_stop would evaluate the callback,
276e78f53d1SNikolas Klauser  // which accesses the internal condition variable, immediately on the same thread.
277e78f53d1SNikolas Klauser  // In this situation, it is OK even without copying a shared ownership the internal
278e78f53d1SNikolas Klauser  // condition variable. However, this needs the evaluation of stop_callback to
279e78f53d1SNikolas Klauser  // happen-before the destruction.
280e78f53d1SNikolas Klauser  // The spec only says "Only the notification to unblock the wait needs to happen
281e78f53d1SNikolas Klauser  // before destruction". To make this work, we need to copy the shared ownership of
282e78f53d1SNikolas Klauser  // the internal condition variable inside this function, which is not possible
283e78f53d1SNikolas Klauser  // with the current ABI.
284e78f53d1SNikolas Klauser  shared_ptr<mutex> __mut = __mut_;
285e78f53d1SNikolas Klauser
286e78f53d1SNikolas Klauser  stop_callback __cb(__stoken, [this] { notify_all(); });
287e78f53d1SNikolas Klauser
288e78f53d1SNikolas Klauser  while (true) {
289e78f53d1SNikolas Klauser    if (__pred())
290e78f53d1SNikolas Klauser      return true;
291e78f53d1SNikolas Klauser
292e78f53d1SNikolas Klauser    // We need to take the internal lock before checking stop_requested,
293e78f53d1SNikolas Klauser    // so that the notification cannot come in between the stop_requested
294e78f53d1SNikolas Klauser    // check and entering the wait.
295e78f53d1SNikolas Klauser    // Note that the stop_callback takes the same internal lock before notifying
296e78f53d1SNikolas Klauser    unique_lock<mutex> __internal_lock(*__mut);
297e78f53d1SNikolas Klauser    if (__stoken.stop_requested())
298e78f53d1SNikolas Klauser      break;
299e78f53d1SNikolas Klauser
300e78f53d1SNikolas Klauser    __unlock_guard<_Lock> __unlock(__user_lock);
301e78f53d1SNikolas Klauser    unique_lock<mutex> __internal_lock2(
302e78f53d1SNikolas Klauser        std::move(__internal_lock)); // switch unlock order between __internal_lock and __user_lock
303e78f53d1SNikolas Klauser    __cv_.wait(__internal_lock2);
304e78f53d1SNikolas Klauser  } // __internal_lock2.unlock(), __user_lock.lock()
305e78f53d1SNikolas Klauser  return __pred();
306e78f53d1SNikolas Klauser}
307e78f53d1SNikolas Klauser
308e78f53d1SNikolas Klausertemplate <class _Lock, class _Clock, class _Duration, class _Predicate>
309e78f53d1SNikolas Klauserbool condition_variable_any::wait_until(
310e78f53d1SNikolas Klauser    _Lock& __user_lock,
311e78f53d1SNikolas Klauser    stop_token __stoken,
312e78f53d1SNikolas Klauser    const chrono::time_point<_Clock, _Duration>& __abs_time,
313e78f53d1SNikolas Klauser    _Predicate __pred) {
314e78f53d1SNikolas Klauser  if (__stoken.stop_requested())
315e78f53d1SNikolas Klauser    return __pred();
316e78f53d1SNikolas Klauser
317e78f53d1SNikolas Klauser  shared_ptr<mutex> __mut = __mut_;
318e78f53d1SNikolas Klauser  stop_callback __cb(__stoken, [this] { notify_all(); });
319e78f53d1SNikolas Klauser
320e78f53d1SNikolas Klauser  while (true) {
321e78f53d1SNikolas Klauser    if (__pred())
322e78f53d1SNikolas Klauser      return true;
323e78f53d1SNikolas Klauser
324e78f53d1SNikolas Klauser    unique_lock<mutex> __internal_lock(*__mut);
325e78f53d1SNikolas Klauser    if (__stoken.stop_requested())
326e78f53d1SNikolas Klauser      break;
327e78f53d1SNikolas Klauser
328e78f53d1SNikolas Klauser    __unlock_guard<_Lock> __unlock(__user_lock);
329e78f53d1SNikolas Klauser    unique_lock<mutex> __internal_lock2(
330e78f53d1SNikolas Klauser        std::move(__internal_lock)); // switch unlock order between __internal_lock and __user_lock
331e78f53d1SNikolas Klauser
332e78f53d1SNikolas Klauser    if (__cv_.wait_until(__internal_lock2, __abs_time) == cv_status::timeout)
333e78f53d1SNikolas Klauser      break;
334e78f53d1SNikolas Klauser  } // __internal_lock2.unlock(), __user_lock.lock()
335e78f53d1SNikolas Klauser  return __pred();
336e78f53d1SNikolas Klauser}
337e78f53d1SNikolas Klauser
338e78f53d1SNikolas Klausertemplate <class _Lock, class _Rep, class _Period, class _Predicate>
339e78f53d1SNikolas Klauserbool condition_variable_any::wait_for(
340e78f53d1SNikolas Klauser    _Lock& __lock, stop_token __stoken, const chrono::duration<_Rep, _Period>& __rel_time, _Predicate __pred) {
341e78f53d1SNikolas Klauser  return wait_until(__lock, std::move(__stoken), chrono::steady_clock::now() + __rel_time, std::move(__pred));
342e78f53d1SNikolas Klauser}
343e78f53d1SNikolas Klauser
344e78f53d1SNikolas Klauser#  endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN)
345e78f53d1SNikolas Klauser
346e78f53d1SNikolas Klauser_LIBCPP_EXPORTED_FROM_ABI void notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>);
347e78f53d1SNikolas Klauser
348e78f53d1SNikolas Klauser_LIBCPP_END_NAMESPACE_STD
349e78f53d1SNikolas Klauser
350e78f53d1SNikolas Klauser#endif // !_LIBCPP_HAS_NO_THREADS
351e78f53d1SNikolas Klauser
352e78f53d1SNikolas Klauser_LIBCPP_POP_MACROS
353e78f53d1SNikolas Klauser
354e78f53d1SNikolas Klauser#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
35573fbae83SNikolas Klauser#  include <__cxx03/atomic>
35673fbae83SNikolas Klauser#  include <__cxx03/concepts>
35773fbae83SNikolas Klauser#  include <__cxx03/cstdint>
35873fbae83SNikolas Klauser#  include <__cxx03/cstdlib>
35973fbae83SNikolas Klauser#  include <__cxx03/cstring>
36073fbae83SNikolas Klauser#  include <__cxx03/initializer_list>
36173fbae83SNikolas Klauser#  include <__cxx03/iosfwd>
36273fbae83SNikolas Klauser#  include <__cxx03/new>
36373fbae83SNikolas Klauser#  include <__cxx03/stdexcept>
36473fbae83SNikolas Klauser#  include <__cxx03/system_error>
36573fbae83SNikolas Klauser#  include <__cxx03/type_traits>
36673fbae83SNikolas Klauser#  include <__cxx03/typeinfo>
367e78f53d1SNikolas Klauser#endif
368e78f53d1SNikolas Klauser
369*ce777190SNikolas Klauser#endif // _LIBCPP___CXX03_CONDITION_VARIABLE
370