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