10b57cec5SDimitry Andric// -*- C++ -*- 2349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 30b57cec5SDimitry Andric// 40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b57cec5SDimitry Andric// 80b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric 100b57cec5SDimitry Andric#ifndef _LIBCPP_CONDITION_VARIABLE 110b57cec5SDimitry Andric#define _LIBCPP_CONDITION_VARIABLE 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric/* 140b57cec5SDimitry Andric condition_variable synopsis 150b57cec5SDimitry Andric 160b57cec5SDimitry Andricnamespace std 170b57cec5SDimitry Andric{ 180b57cec5SDimitry Andric 190b57cec5SDimitry Andricenum class cv_status { no_timeout, timeout }; 200b57cec5SDimitry Andric 210b57cec5SDimitry Andricclass condition_variable 220b57cec5SDimitry Andric{ 230b57cec5SDimitry Andricpublic: 240b57cec5SDimitry Andric condition_variable(); 250b57cec5SDimitry Andric ~condition_variable(); 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric condition_variable(const condition_variable&) = delete; 280b57cec5SDimitry Andric condition_variable& operator=(const condition_variable&) = delete; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric void notify_one() noexcept; 310b57cec5SDimitry Andric void notify_all() noexcept; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric void wait(unique_lock<mutex>& lock); 340b57cec5SDimitry Andric template <class Predicate> 350b57cec5SDimitry Andric void wait(unique_lock<mutex>& lock, Predicate pred); 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric template <class Clock, class Duration> 380b57cec5SDimitry Andric cv_status 390b57cec5SDimitry Andric wait_until(unique_lock<mutex>& lock, 400b57cec5SDimitry Andric const chrono::time_point<Clock, Duration>& abs_time); 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric template <class Clock, class Duration, class Predicate> 430b57cec5SDimitry Andric bool 440b57cec5SDimitry Andric wait_until(unique_lock<mutex>& lock, 450b57cec5SDimitry Andric const chrono::time_point<Clock, Duration>& abs_time, 460b57cec5SDimitry Andric Predicate pred); 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric template <class Rep, class Period> 490b57cec5SDimitry Andric cv_status 500b57cec5SDimitry Andric wait_for(unique_lock<mutex>& lock, 510b57cec5SDimitry Andric const chrono::duration<Rep, Period>& rel_time); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric template <class Rep, class Period, class Predicate> 540b57cec5SDimitry Andric bool 550b57cec5SDimitry Andric wait_for(unique_lock<mutex>& lock, 560b57cec5SDimitry Andric const chrono::duration<Rep, Period>& rel_time, 570b57cec5SDimitry Andric Predicate pred); 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric typedef pthread_cond_t* native_handle_type; 600b57cec5SDimitry Andric native_handle_type native_handle(); 610b57cec5SDimitry Andric}; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andricvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andricclass condition_variable_any 660b57cec5SDimitry Andric{ 670b57cec5SDimitry Andricpublic: 680b57cec5SDimitry Andric condition_variable_any(); 690b57cec5SDimitry Andric ~condition_variable_any(); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric condition_variable_any(const condition_variable_any&) = delete; 720b57cec5SDimitry Andric condition_variable_any& operator=(const condition_variable_any&) = delete; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric void notify_one() noexcept; 750b57cec5SDimitry Andric void notify_all() noexcept; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric template <class Lock> 780b57cec5SDimitry Andric void wait(Lock& lock); 790b57cec5SDimitry Andric template <class Lock, class Predicate> 800b57cec5SDimitry Andric void wait(Lock& lock, Predicate pred); 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric template <class Lock, class Clock, class Duration> 830b57cec5SDimitry Andric cv_status 840b57cec5SDimitry Andric wait_until(Lock& lock, 850b57cec5SDimitry Andric const chrono::time_point<Clock, Duration>& abs_time); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric template <class Lock, class Clock, class Duration, class Predicate> 880b57cec5SDimitry Andric bool 890b57cec5SDimitry Andric wait_until(Lock& lock, 900b57cec5SDimitry Andric const chrono::time_point<Clock, Duration>& abs_time, 910b57cec5SDimitry Andric Predicate pred); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric template <class Lock, class Rep, class Period> 940b57cec5SDimitry Andric cv_status 950b57cec5SDimitry Andric wait_for(Lock& lock, 960b57cec5SDimitry Andric const chrono::duration<Rep, Period>& rel_time); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric template <class Lock, class Rep, class Period, class Predicate> 990b57cec5SDimitry Andric bool 1000b57cec5SDimitry Andric wait_for(Lock& lock, 1010b57cec5SDimitry Andric const chrono::duration<Rep, Period>& rel_time, 1020b57cec5SDimitry Andric Predicate pred); 103c9157d92SDimitry Andric 104c9157d92SDimitry Andric // [thread.condvarany.intwait], interruptible waits 105c9157d92SDimitry Andric template <class Lock, class Predicate> 106c9157d92SDimitry Andric bool wait(Lock& lock, stop_token stoken, Predicate pred); // since C++20 107c9157d92SDimitry Andric 108c9157d92SDimitry Andric template <class Lock, class Clock, class Duration, class Predicate> 109c9157d92SDimitry Andric bool wait_until(Lock& lock, stop_token stoken, 110c9157d92SDimitry Andric const chrono::time_point<Clock, Duration>& abs_time, Predicate pred); // since C++20 111c9157d92SDimitry Andric 112c9157d92SDimitry Andric template <class Lock, class Rep, class Period, class Predicate> 113c9157d92SDimitry Andric bool wait_for(Lock& lock, stop_token stoken, 114c9157d92SDimitry Andric const chrono::duration<Rep, Period>& rel_time, Predicate pred); // since C++20 1150b57cec5SDimitry Andric}; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric} // std 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric*/ 1200b57cec5SDimitry Andric 12181ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler 122c9157d92SDimitry Andric#include <__availability> 123fe013be4SDimitry Andric#include <__chrono/duration.h> 124fe013be4SDimitry Andric#include <__chrono/steady_clock.h> 125fe013be4SDimitry Andric#include <__chrono/time_point.h> 126fe013be4SDimitry Andric#include <__condition_variable/condition_variable.h> 1270b57cec5SDimitry Andric#include <__config> 128bdd1243dSDimitry Andric#include <__memory/shared_ptr.h> 129fe013be4SDimitry Andric#include <__mutex/lock_guard.h> 130fe013be4SDimitry Andric#include <__mutex/mutex.h> 131fe013be4SDimitry Andric#include <__mutex/tag_types.h> 132fe013be4SDimitry Andric#include <__mutex/unique_lock.h> 133a58f00eaSDimitry Andric#include <__stop_token/stop_callback.h> 134c9157d92SDimitry Andric#include <__stop_token/stop_token.h> 135fe013be4SDimitry Andric#include <__utility/move.h> 13604eeddc0SDimitry Andric#include <version> 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1390b57cec5SDimitry Andric# pragma GCC system_header 1400b57cec5SDimitry Andric#endif 1410b57cec5SDimitry Andric 142*b9d9368bSDimitry Andric_LIBCPP_PUSH_MACROS 143*b9d9368bSDimitry Andric#include <__undef_macros> 144*b9d9368bSDimitry Andric 1450b57cec5SDimitry Andric#ifndef _LIBCPP_HAS_NO_THREADS 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 1480b57cec5SDimitry Andric 149e710425bSDimitry Andricclass _LIBCPP_EXPORTED_FROM_ABI condition_variable_any { 1500b57cec5SDimitry Andric condition_variable __cv_; 1510b57cec5SDimitry Andric shared_ptr<mutex> __mut_; 1520b57cec5SDimitry Andric 153e710425bSDimitry Andricpublic: 154e710425bSDimitry Andric _LIBCPP_HIDE_FROM_ABI condition_variable_any(); 155e710425bSDimitry Andric 156e710425bSDimitry Andric _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT; 157e710425bSDimitry Andric _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric template <class _Lock> 160e710425bSDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS void wait(_Lock& __lock); 1610b57cec5SDimitry Andric template <class _Lock, class _Predicate> 162e710425bSDimitry Andric _LIBCPP_HIDE_FROM_ABI void wait(_Lock& __lock, _Predicate __pred); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric template <class _Lock, class _Clock, class _Duration> 165e710425bSDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status 166e710425bSDimitry Andric wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t); 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric template <class _Lock, class _Clock, class _Duration, class _Predicate> 169e710425bSDimitry Andric bool _LIBCPP_HIDE_FROM_ABI 170e710425bSDimitry Andric wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric template <class _Lock, class _Rep, class _Period> 173e710425bSDimitry Andric cv_status _LIBCPP_HIDE_FROM_ABI wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __d); 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric template <class _Lock, class _Rep, class _Period, class _Predicate> 176e710425bSDimitry Andric bool _LIBCPP_HIDE_FROM_ABI wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred); 177c9157d92SDimitry Andric 178c9157d92SDimitry Andric# if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) 179c9157d92SDimitry Andric 180c9157d92SDimitry Andric template <class _Lock, class _Predicate> 181c9157d92SDimitry Andric _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait(_Lock& __lock, stop_token __stoken, _Predicate __pred); 182c9157d92SDimitry Andric 183c9157d92SDimitry Andric template <class _Lock, class _Clock, class _Duration, class _Predicate> 184e710425bSDimitry Andric _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool wait_until( 185e710425bSDimitry Andric _Lock& __lock, stop_token __stoken, const chrono::time_point<_Clock, _Duration>& __abs_time, _Predicate __pred); 186c9157d92SDimitry Andric 187c9157d92SDimitry Andric template <class _Lock, class _Rep, class _Period, class _Predicate> 188e710425bSDimitry Andric _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool 189e710425bSDimitry Andric wait_for(_Lock& __lock, stop_token __stoken, const chrono::duration<_Rep, _Period>& __rel_time, _Predicate __pred); 190c9157d92SDimitry Andric 191c9157d92SDimitry Andric# endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) 1920b57cec5SDimitry Andric}; 1930b57cec5SDimitry Andric 194e710425bSDimitry Andricinline condition_variable_any::condition_variable_any() : __mut_(make_shared<mutex>()) {} 1950b57cec5SDimitry Andric 196e710425bSDimitry Andricinline void condition_variable_any::notify_one() _NOEXCEPT { 1970b57cec5SDimitry Andric { lock_guard<mutex> __lx(*__mut_); } 1980b57cec5SDimitry Andric __cv_.notify_one(); 1990b57cec5SDimitry Andric} 2000b57cec5SDimitry Andric 201e710425bSDimitry Andricinline void condition_variable_any::notify_all() _NOEXCEPT { 2020b57cec5SDimitry Andric { lock_guard<mutex> __lx(*__mut_); } 2030b57cec5SDimitry Andric __cv_.notify_all(); 2040b57cec5SDimitry Andric} 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andrictemplate <class _Lock> 207a58f00eaSDimitry Andricstruct __unlock_guard { 208a58f00eaSDimitry Andric _Lock& __lock_; 209a58f00eaSDimitry Andric 210a58f00eaSDimitry Andric _LIBCPP_HIDE_FROM_ABI __unlock_guard(_Lock& __lock) : __lock_(__lock) { __lock_.unlock(); } 211a58f00eaSDimitry Andric 212a58f00eaSDimitry Andric _LIBCPP_HIDE_FROM_ABI ~__unlock_guard() _NOEXCEPT // turns exception to std::terminate 213a58f00eaSDimitry Andric { 214a58f00eaSDimitry Andric __lock_.lock(); 215e710425bSDimitry Andric } 216a58f00eaSDimitry Andric 217a58f00eaSDimitry Andric __unlock_guard(const __unlock_guard&) = delete; 218a58f00eaSDimitry Andric __unlock_guard& operator=(const __unlock_guard&) = delete; 2190b57cec5SDimitry Andric}; 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andrictemplate <class _Lock> 222e710425bSDimitry Andricvoid condition_variable_any::wait(_Lock& __lock) { 2230b57cec5SDimitry Andric shared_ptr<mutex> __mut = __mut_; 2240b57cec5SDimitry Andric unique_lock<mutex> __lk(*__mut); 225a58f00eaSDimitry Andric __unlock_guard<_Lock> __unlock(__lock); 226fe013be4SDimitry Andric lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t()); 2270b57cec5SDimitry Andric __cv_.wait(__lk); 2280b57cec5SDimitry Andric} // __mut_.unlock(), __lock.lock() 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andrictemplate <class _Lock, class _Predicate> 231e710425bSDimitry Andricinline void condition_variable_any::wait(_Lock& __lock, _Predicate __pred) { 2320b57cec5SDimitry Andric while (!__pred()) 2330b57cec5SDimitry Andric wait(__lock); 2340b57cec5SDimitry Andric} 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andrictemplate <class _Lock, class _Clock, class _Duration> 237e710425bSDimitry Andriccv_status condition_variable_any::wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t) { 2380b57cec5SDimitry Andric shared_ptr<mutex> __mut = __mut_; 2390b57cec5SDimitry Andric unique_lock<mutex> __lk(*__mut); 240a58f00eaSDimitry Andric __unlock_guard<_Lock> __unlock(__lock); 241fe013be4SDimitry Andric lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t()); 2420b57cec5SDimitry Andric return __cv_.wait_until(__lk, __t); 2430b57cec5SDimitry Andric} // __mut_.unlock(), __lock.lock() 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andrictemplate <class _Lock, class _Clock, class _Duration, class _Predicate> 246e710425bSDimitry Andricinline bool 247e710425bSDimitry Andriccondition_variable_any::wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) { 2480b57cec5SDimitry Andric while (!__pred()) 2490b57cec5SDimitry Andric if (wait_until(__lock, __t) == cv_status::timeout) 2500b57cec5SDimitry Andric return __pred(); 2510b57cec5SDimitry Andric return true; 2520b57cec5SDimitry Andric} 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andrictemplate <class _Lock, class _Rep, class _Period> 255e710425bSDimitry Andricinline cv_status condition_variable_any::wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __d) { 2560b57cec5SDimitry Andric return wait_until(__lock, chrono::steady_clock::now() + __d); 2570b57cec5SDimitry Andric} 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andrictemplate <class _Lock, class _Rep, class _Period, class _Predicate> 260e710425bSDimitry Andricinline bool 261e710425bSDimitry Andriccondition_variable_any::wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred) { 262e710425bSDimitry Andric return wait_until(__lock, chrono::steady_clock::now() + __d, std::move(__pred)); 2630b57cec5SDimitry Andric} 2640b57cec5SDimitry Andric 265c9157d92SDimitry Andric# if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) 266c9157d92SDimitry Andric 267c9157d92SDimitry Andrictemplate <class _Lock, class _Predicate> 268a58f00eaSDimitry Andricbool condition_variable_any::wait(_Lock& __user_lock, stop_token __stoken, _Predicate __pred) { 269a58f00eaSDimitry Andric if (__stoken.stop_requested()) 270a58f00eaSDimitry Andric return __pred(); 271a58f00eaSDimitry Andric 272a58f00eaSDimitry Andric // Per https://eel.is/c++draft/thread.condition.condvarany#general-note-2, 273a58f00eaSDimitry Andric // we do need to take a copy of the shared pointer __mut_ 274a58f00eaSDimitry Andric // This ensures that a thread can call the destructor immediately after calling 275a58f00eaSDimitry Andric // notify_all, without waiting all the wait calls. 276a58f00eaSDimitry Andric // A thread can also safely call the destructor immediately after calling 277a58f00eaSDimitry Andric // request_stop, as the call to request_stop would evaluate the callback, 278a58f00eaSDimitry Andric // which accesses the internal condition variable, immediately on the same thread. 279a58f00eaSDimitry Andric // In this situation, it is OK even without copying a shared ownership the internal 280a58f00eaSDimitry Andric // condition variable. However, this needs the evaluation of stop_callback to 281a58f00eaSDimitry Andric // happen-before the destruction. 282a58f00eaSDimitry Andric // The spec only says "Only the notification to unblock the wait needs to happen 283a58f00eaSDimitry Andric // before destruction". To make this work, we need to copy the shared ownership of 284a58f00eaSDimitry Andric // the internal condition variable inside this function, which is not possible 285a58f00eaSDimitry Andric // with the current ABI. 286a58f00eaSDimitry Andric shared_ptr<mutex> __mut = __mut_; 287a58f00eaSDimitry Andric 288a58f00eaSDimitry Andric stop_callback __cb(__stoken, [this] { notify_all(); }); 289a58f00eaSDimitry Andric 290a58f00eaSDimitry Andric while (true) { 291c9157d92SDimitry Andric if (__pred()) 292c9157d92SDimitry Andric return true; 293a58f00eaSDimitry Andric 294a58f00eaSDimitry Andric // We need to take the internal lock before checking stop_requested, 295a58f00eaSDimitry Andric // so that the notification cannot come in between the stop_requested 296a58f00eaSDimitry Andric // check and entering the wait. 297a58f00eaSDimitry Andric // Note that the stop_callback takes the same internal lock before notifying 298a58f00eaSDimitry Andric unique_lock<mutex> __internal_lock(*__mut); 299a58f00eaSDimitry Andric if (__stoken.stop_requested()) 300a58f00eaSDimitry Andric break; 301a58f00eaSDimitry Andric 302a58f00eaSDimitry Andric __unlock_guard<_Lock> __unlock(__user_lock); 303a58f00eaSDimitry Andric unique_lock<mutex> __internal_lock2( 304a58f00eaSDimitry Andric std::move(__internal_lock)); // switch unlock order between __internal_lock and __user_lock 305a58f00eaSDimitry Andric __cv_.wait(__internal_lock2); 306a58f00eaSDimitry Andric } // __internal_lock2.unlock(), __user_lock.lock() 307c9157d92SDimitry Andric return __pred(); 308c9157d92SDimitry Andric} 309c9157d92SDimitry Andric 310c9157d92SDimitry Andrictemplate <class _Lock, class _Clock, class _Duration, class _Predicate> 311c9157d92SDimitry Andricbool condition_variable_any::wait_until( 312a58f00eaSDimitry Andric _Lock& __user_lock, 313a58f00eaSDimitry Andric stop_token __stoken, 314a58f00eaSDimitry Andric const chrono::time_point<_Clock, _Duration>& __abs_time, 315a58f00eaSDimitry Andric _Predicate __pred) { 316a58f00eaSDimitry Andric if (__stoken.stop_requested()) 317a58f00eaSDimitry Andric return __pred(); 318a58f00eaSDimitry Andric 319a58f00eaSDimitry Andric shared_ptr<mutex> __mut = __mut_; 320a58f00eaSDimitry Andric stop_callback __cb(__stoken, [this] { notify_all(); }); 321a58f00eaSDimitry Andric 322a58f00eaSDimitry Andric while (true) { 323c9157d92SDimitry Andric if (__pred()) 324c9157d92SDimitry Andric return true; 325a58f00eaSDimitry Andric 326a58f00eaSDimitry Andric unique_lock<mutex> __internal_lock(*__mut); 327a58f00eaSDimitry Andric if (__stoken.stop_requested()) 328a58f00eaSDimitry Andric break; 329a58f00eaSDimitry Andric 330a58f00eaSDimitry Andric __unlock_guard<_Lock> __unlock(__user_lock); 331a58f00eaSDimitry Andric unique_lock<mutex> __internal_lock2( 332a58f00eaSDimitry Andric std::move(__internal_lock)); // switch unlock order between __internal_lock and __user_lock 333a58f00eaSDimitry Andric 334a58f00eaSDimitry Andric if (__cv_.wait_until(__internal_lock2, __abs_time) == cv_status::timeout) 335a58f00eaSDimitry Andric break; 336a58f00eaSDimitry Andric } // __internal_lock2.unlock(), __user_lock.lock() 337c9157d92SDimitry Andric return __pred(); 338c9157d92SDimitry Andric} 339c9157d92SDimitry Andric 340c9157d92SDimitry Andrictemplate <class _Lock, class _Rep, class _Period, class _Predicate> 341c9157d92SDimitry Andricbool condition_variable_any::wait_for( 342c9157d92SDimitry Andric _Lock& __lock, stop_token __stoken, const chrono::duration<_Rep, _Period>& __rel_time, _Predicate __pred) { 343c9157d92SDimitry Andric return wait_until(__lock, std::move(__stoken), chrono::steady_clock::now() + __rel_time, std::move(__pred)); 344c9157d92SDimitry Andric} 345c9157d92SDimitry Andric 346c9157d92SDimitry Andric# endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) 347c9157d92SDimitry Andric 348fe013be4SDimitry Andric_LIBCPP_EXPORTED_FROM_ABI void notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>); 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS 3530b57cec5SDimitry Andric 354*b9d9368bSDimitry Andric_LIBCPP_POP_MACROS 355*b9d9368bSDimitry Andric 356bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 357fe013be4SDimitry Andric# include <atomic> 358bdd1243dSDimitry Andric# include <concepts> 359fe013be4SDimitry Andric# include <cstdint> 360fe013be4SDimitry Andric# include <cstdlib> 361fe013be4SDimitry Andric# include <cstring> 362fe013be4SDimitry Andric# include <initializer_list> 363c9157d92SDimitry Andric# include <iosfwd> 364fe013be4SDimitry Andric# include <new> 365fe013be4SDimitry Andric# include <stdexcept> 366fe013be4SDimitry Andric# include <system_error> 367bdd1243dSDimitry Andric# include <type_traits> 368fe013be4SDimitry Andric# include <typeinfo> 369bdd1243dSDimitry Andric#endif 370bdd1243dSDimitry Andric 3710b57cec5SDimitry Andric#endif // _LIBCPP_CONDITION_VARIABLE 372