1068 lines
42 KiB
Markdown
1068 lines
42 KiB
Markdown
[thread.condition]
|
||
|
||
# 32 Concurrency support library [[thread]](./#thread)
|
||
|
||
## 32.7 Condition variables [thread.condition]
|
||
|
||
### [32.7.1](#general) General [[thread.condition.general]](thread.condition.general)
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9482)
|
||
|
||
Condition variables provide synchronization primitives used to block a thread until
|
||
notified by some other thread that some condition is met or until a system time is
|
||
reached[.](#general-1.sentence-1)
|
||
|
||
Class condition_variable provides a condition variable that can only
|
||
wait on an object of type unique_lock<mutex>, allowing the implementation
|
||
to be more efficient[.](#general-1.sentence-2)
|
||
|
||
Class condition_variable_any provides a general
|
||
condition variable that can wait on objects of user-supplied lock types[.](#general-1.sentence-3)
|
||
|
||
[2](#general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9490)
|
||
|
||
Condition variables permit concurrent invocation of the wait, wait_for,wait_until, notify_one and notify_all member functions[.](#general-2.sentence-1)
|
||
|
||
[3](#general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9494)
|
||
|
||
The executions of notify_one and notify_all are atomic[.](#general-3.sentence-1)
|
||
|
||
The executions of wait, wait_for, and wait_until are performed
|
||
in three atomic parts:
|
||
|
||
| [1.](#general-3.1) | the release of the mutex and entry into the waiting state; |
|
||
| --- | --- |
|
||
| [2.](#general-3.2) | the unblocking of the wait; and |
|
||
| [3.](#general-3.3) | the reacquisition of the lock[.](#general-3.sentence-2) |
|
||
|
||
[4](#general-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9505)
|
||
|
||
The implementation behaves as if all executions of notify_one, notify_all, and each
|
||
part of the wait, wait_for, and wait_until executions are
|
||
executed in a single unspecified total order consistent with the âhappens beforeâ order[.](#general-4.sentence-1)
|
||
|
||
[5](#general-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9510)
|
||
|
||
Condition variable construction and destruction need not be synchronized[.](#general-5.sentence-1)
|
||
|
||
### [32.7.2](#condition.variable.syn) Header <condition_variable> synopsis [[condition.variable.syn]](condition.variable.syn)
|
||
|
||
[ð](#header:%3ccondition_variable%3e)
|
||
|
||
namespace std {// [[thread.condition.condvar]](#condvar "32.7.4 Class condition_variable"), class condition_variableclass condition_variable; // [[thread.condition.condvarany]](#condvarany "32.7.5 Class condition_variable_any"), class condition_variable_anyclass condition_variable_any; // [[thread.condition.nonmember]](#nonmember "32.7.3 Non-member functions"), non-member functionsvoid notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); enum class [cv_status](#lib:cv_status "32.7.2 Header <condition_variable> synopsis [condition.variable.syn]") { [no_timeout](#lib:cv_status,no_timeout "32.7.2 Header <condition_variable> synopsis [condition.variable.syn]"), [timeout](#lib:cv_status,timeout "32.7.2 Header <condition_variable> synopsis [condition.variable.syn]") };}
|
||
|
||
### [32.7.3](#nonmember) Non-member functions [[thread.condition.nonmember]](thread.condition.nonmember)
|
||
|
||
[ð](#lib:notify_all_at_thread_exit)
|
||
|
||
`void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
|
||
`
|
||
|
||
[1](#nonmember-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9537)
|
||
|
||
*Preconditions*: lk is locked by the calling thread and either
|
||
|
||
- [(1.1)](#nonmember-1.1)
|
||
|
||
no other thread is waiting on cond, or
|
||
|
||
- [(1.2)](#nonmember-1.2)
|
||
|
||
lk.mutex() returns the same value for each of the lock arguments
|
||
supplied by all concurrently waiting (via wait, wait_for,
|
||
or wait_until) threads[.](#nonmember-1.sentence-1)
|
||
|
||
[2](#nonmember-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9547)
|
||
|
||
*Effects*: Transfers ownership of the lock associated with lk into
|
||
internal storage and schedules cond to be notified when the current
|
||
thread exits, after all objects with thread storage duration associated with
|
||
the current thread have been destroyed[.](#nonmember-2.sentence-1)
|
||
|
||
This notification is equivalent to:lk.unlock();
|
||
cond.notify_all();
|
||
|
||
[3](#nonmember-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9558)
|
||
|
||
*Synchronization*: The implied lk.unlock() call is sequenced after the destruction of
|
||
all objects with thread storage duration associated with the current thread[.](#nonmember-3.sentence-1)
|
||
|
||
[4](#nonmember-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9563)
|
||
|
||
[*Note [1](#nonmember-note-1)*:
|
||
|
||
The supplied lock is held until the thread exits,
|
||
which might cause deadlock due to lock ordering issues[.](#nonmember-4.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[5](#nonmember-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9569)
|
||
|
||
[*Note [2](#nonmember-note-2)*:
|
||
|
||
It is the user's responsibility to ensure that waiting threads
|
||
do not incorrectly assume that the thread has finished if they experience
|
||
spurious wakeups[.](#nonmember-5.sentence-1)
|
||
|
||
This typically requires that the condition being waited
|
||
for is satisfied while holding the lock on lk, and that this lock
|
||
is not released and reacquired prior to calling notify_all_at_thread_exit[.](#nonmember-5.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
### [32.7.4](#condvar) Class condition_variable [[thread.condition.condvar]](thread.condition.condvar)
|
||
|
||
[ð](#lib:condition_variable)
|
||
|
||
namespace std {class condition_variable {public: condition_variable(); ~condition_variable();
|
||
|
||
condition_variable(const condition_variable&) = delete;
|
||
condition_variable& operator=(const condition_variable&) = delete; void notify_one() noexcept; void notify_all() noexcept; void wait(unique_lock<mutex>& lock); template<class Predicate>void wait(unique_lock<mutex>& lock, Predicate pred); template<class Clock, class Duration> cv_status wait_until(unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time); template<class Clock, class Duration, class Predicate>bool wait_until(unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time,
|
||
Predicate pred); template<class Rep, class Period> cv_status wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time); template<class Rep, class Period, class Predicate>bool wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time,
|
||
Predicate pred); using native_handle_type = *implementation-defined*; // see [[thread.req.native]](thread.req.native "32.2.3 Native handles") native_handle_type native_handle(); // see [[thread.req.native]](thread.req.native "32.2.3 Native handles")};}
|
||
|
||
[1](#condvar-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9618)
|
||
|
||
The class condition_variable is a standard-layout class ([[class.prop]](class.prop "11.2 Properties of classes"))[.](#condvar-1.sentence-1)
|
||
|
||
[ð](#lib:condition_variable,constructor)
|
||
|
||
`condition_variable();
|
||
`
|
||
|
||
[2](#condvar-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9627)
|
||
|
||
*Throws*: system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#condvar-2.sentence-1)
|
||
|
||
[3](#condvar-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9631)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(3.1)](#condvar-3.1)
|
||
|
||
resource_unavailable_try_again â if some non-memory resource
|
||
limitation prevents initialization[.](#condvar-3.sentence-1)
|
||
|
||
[ð](#lib:condition_variable,destructor)
|
||
|
||
`~condition_variable();
|
||
`
|
||
|
||
[4](#condvar-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9645)
|
||
|
||
*Preconditions*: There is no thread blocked on *this[.](#condvar-4.sentence-1)
|
||
|
||
[*Note [1](#condvar-note-1)*:
|
||
|
||
That is, all
|
||
threads have been notified; they can subsequently block on the lock specified in the
|
||
wait[.](#condvar-4.sentence-2)
|
||
|
||
This relaxes the usual rules, which would have required all wait calls to happen before
|
||
destruction[.](#condvar-4.sentence-3)
|
||
|
||
Only the notification to unblock the wait needs to happen before destruction[.](#condvar-4.sentence-4)
|
||
|
||
Undefined behavior ensues if a thread waits on *this once the destructor has
|
||
been started, especially when the waiting threads are calling the wait functions in a loop or
|
||
using the overloads of wait, wait_for, or wait_until that take a predicate[.](#condvar-4.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:notify_one,condition_variable)
|
||
|
||
`void notify_one() noexcept;
|
||
`
|
||
|
||
[5](#condvar-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9666)
|
||
|
||
*Effects*: If any threads are blocked waiting for *this, unblocks one of those threads[.](#condvar-5.sentence-1)
|
||
|
||
[ð](#lib:notify_all,condition_variable)
|
||
|
||
`void notify_all() noexcept;
|
||
`
|
||
|
||
[6](#condvar-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9677)
|
||
|
||
*Effects*: Unblocks all threads that are blocked waiting for *this[.](#condvar-6.sentence-1)
|
||
|
||
[ð](#lib:wait,condition_variable)
|
||
|
||
`void wait(unique_lock<mutex>& lock);
|
||
`
|
||
|
||
[7](#condvar-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9688)
|
||
|
||
*Preconditions*: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either
|
||
|
||
- [(7.1)](#condvar-7.1)
|
||
|
||
no other thread is waiting on this condition_variable object or
|
||
|
||
- [(7.2)](#condvar-7.2)
|
||
|
||
lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait,wait_for, or wait_until) threads[.](#condvar-7.sentence-1)
|
||
|
||
[8](#condvar-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9699)
|
||
|
||
*Effects*:
|
||
|
||
- [(8.1)](#condvar-8.1)
|
||
|
||
Atomically calls lock.unlock() and blocks on *this[.](#condvar-8.1.sentence-1)
|
||
|
||
- [(8.2)](#condvar-8.2)
|
||
|
||
When unblocked, calls lock.lock() (possibly blocking on the lock), then returns[.](#condvar-8.2.sentence-1)
|
||
|
||
- [(8.3)](#condvar-8.3)
|
||
|
||
The function will unblock when signaled by a call to notify_one() or a call to notify_all(), or spuriously[.](#condvar-8.3.sentence-1)
|
||
|
||
[9](#condvar-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9709)
|
||
|
||
*Postconditions*: lock.owns_lock() is true and lock.mutex() is locked by the calling thread[.](#condvar-9.sentence-1)
|
||
|
||
[10](#condvar-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9714)
|
||
|
||
*Throws*: Nothing[.](#condvar-10.sentence-1)
|
||
|
||
[11](#condvar-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9718)
|
||
|
||
*Remarks*: If the function fails to meet the postcondition, terminate() is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#condvar-11.sentence-1)
|
||
|
||
[*Note [2](#condvar-note-2)*:
|
||
|
||
This can happen if the re-locking of the mutex throws an exception[.](#condvar-11.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:wait,condition_variable_)
|
||
|
||
`template<class Predicate>
|
||
void wait(unique_lock<mutex>& lock, Predicate pred);
|
||
`
|
||
|
||
[12](#condvar-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9734)
|
||
|
||
*Preconditions*: lock.owns_lock() is true and lock.mutex() is
|
||
locked by the calling thread, and either
|
||
|
||
- [(12.1)](#condvar-12.1)
|
||
|
||
no other thread is waiting on this condition_variable object or
|
||
|
||
- [(12.2)](#condvar-12.2)
|
||
|
||
lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait,wait_for, or wait_until) threads[.](#condvar-12.sentence-1)
|
||
|
||
[13](#condvar-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9745)
|
||
|
||
*Effects*: Equivalent to:while (!pred()) wait(lock);
|
||
|
||
[14](#condvar-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9753)
|
||
|
||
*Postconditions*: lock.owns_lock() is true and lock.mutex() is locked by the calling thread[.](#condvar-14.sentence-1)
|
||
|
||
[15](#condvar-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9758)
|
||
|
||
*Throws*: Any exception thrown by pred[.](#condvar-15.sentence-1)
|
||
|
||
[16](#condvar-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9762)
|
||
|
||
*Remarks*: If the function fails to meet the postcondition, terminate() is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#condvar-16.sentence-1)
|
||
|
||
[*Note [3](#condvar-note-3)*:
|
||
|
||
This can happen if the re-locking of the mutex throws an exception[.](#condvar-16.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:wait_until,condition_variable)
|
||
|
||
`template<class Clock, class Duration>
|
||
cv_status wait_until(unique_lock<mutex>& lock,
|
||
const chrono::time_point<Clock, Duration>& abs_time);
|
||
`
|
||
|
||
[17](#condvar-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9779)
|
||
|
||
*Preconditions*: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either
|
||
|
||
- [(17.1)](#condvar-17.1)
|
||
|
||
no other thread is waiting on this condition_variable object or
|
||
|
||
- [(17.2)](#condvar-17.2)
|
||
|
||
lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait,wait_for, or wait_until) threads[.](#condvar-17.sentence-1)
|
||
|
||
[18](#condvar-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9790)
|
||
|
||
*Effects*:
|
||
|
||
- [(18.1)](#condvar-18.1)
|
||
|
||
Atomically calls lock.unlock() and blocks on *this[.](#condvar-18.1.sentence-1)
|
||
|
||
- [(18.2)](#condvar-18.2)
|
||
|
||
When unblocked, calls lock.lock() (possibly blocking on the lock), then returns[.](#condvar-18.2.sentence-1)
|
||
|
||
- [(18.3)](#condvar-18.3)
|
||
|
||
The function will unblock when signaled by a call to notify_one(), a call to notify_all(),
|
||
expiration of the absolute timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified by abs_time,
|
||
or spuriously[.](#condvar-18.3.sentence-1)
|
||
|
||
- [(18.4)](#condvar-18.4)
|
||
|
||
If the function exits via an exception, lock.lock() is called prior to exiting the function[.](#condvar-18.4.sentence-1)
|
||
|
||
[19](#condvar-19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9808)
|
||
|
||
*Postconditions*: lock.owns_lock() is true and lock.mutex() is locked by the calling thread[.](#condvar-19.sentence-1)
|
||
|
||
[20](#condvar-20)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9813)
|
||
|
||
*Returns*: cv_status::timeout if
|
||
the absolute timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified by abs_time expired,
|
||
otherwise cv_status::no_timeout[.](#condvar-20.sentence-1)
|
||
|
||
[21](#condvar-21)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9819)
|
||
|
||
*Throws*: Timeout-related
|
||
exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))[.](#condvar-21.sentence-1)
|
||
|
||
[22](#condvar-22)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9824)
|
||
|
||
*Remarks*: If the function fails to meet the postcondition, terminate() is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#condvar-22.sentence-1)
|
||
|
||
[*Note [4](#condvar-note-4)*:
|
||
|
||
This can happen if the re-locking of the mutex throws an exception[.](#condvar-22.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:wait_for,condition_variable)
|
||
|
||
`template<class Rep, class Period>
|
||
cv_status wait_for(unique_lock<mutex>& lock,
|
||
const chrono::duration<Rep, Period>& rel_time);
|
||
`
|
||
|
||
[23](#condvar-23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9841)
|
||
|
||
*Preconditions*: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either
|
||
|
||
- [(23.1)](#condvar-23.1)
|
||
|
||
no other thread is waiting on this condition_variable object or
|
||
|
||
- [(23.2)](#condvar-23.2)
|
||
|
||
lock.mutex() returns the same value for each of the lock arguments
|
||
supplied by all concurrently waiting (via wait, wait_for, orwait_until) threads[.](#condvar-23.sentence-1)
|
||
|
||
[24](#condvar-24)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9852)
|
||
|
||
*Effects*: Equivalent to:return wait_until(lock, chrono::steady_clock::now() + rel_time);
|
||
|
||
[25](#condvar-25)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9859)
|
||
|
||
*Postconditions*: lock.owns_lock() is true and lock.mutex() is locked by the calling thread[.](#condvar-25.sentence-1)
|
||
|
||
[26](#condvar-26)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9864)
|
||
|
||
*Returns*: cv_status::timeout if
|
||
the relative timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified by rel_time expired,
|
||
otherwise cv_status::no_timeout[.](#condvar-26.sentence-1)
|
||
|
||
[27](#condvar-27)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9870)
|
||
|
||
*Throws*: Timeout-related
|
||
exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))[.](#condvar-27.sentence-1)
|
||
|
||
[28](#condvar-28)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9875)
|
||
|
||
*Remarks*: If the function fails to meet the postcondition, terminate is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#condvar-28.sentence-1)
|
||
|
||
[*Note [5](#condvar-note-5)*:
|
||
|
||
This can happen if the re-locking of the mutex throws an exception[.](#condvar-28.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:wait_until,condition_variable_)
|
||
|
||
`template<class Clock, class Duration, class Predicate>
|
||
bool wait_until(unique_lock<mutex>& lock,
|
||
const chrono::time_point<Clock, Duration>& abs_time,
|
||
Predicate pred);
|
||
`
|
||
|
||
[29](#condvar-29)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9893)
|
||
|
||
*Preconditions*: lock.owns_lock() is true and lock.mutex() is
|
||
locked by the calling thread, and either
|
||
|
||
- [(29.1)](#condvar-29.1)
|
||
|
||
no other thread is waiting on this condition_variable object or
|
||
|
||
- [(29.2)](#condvar-29.2)
|
||
|
||
lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait,wait_for, or wait_until) threads[.](#condvar-29.sentence-1)
|
||
|
||
[30](#condvar-30)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9904)
|
||
|
||
*Effects*: Equivalent to:while (!pred())if (wait_until(lock, abs_time) == cv_status::timeout)return pred();return true;
|
||
|
||
[31](#condvar-31)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9914)
|
||
|
||
*Postconditions*: lock.owns_lock() is true and lock.mutex() is locked by the calling thread[.](#condvar-31.sentence-1)
|
||
|
||
[32](#condvar-32)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9919)
|
||
|
||
[*Note [6](#condvar-note-6)*:
|
||
|
||
The returned value indicates whether the predicate evaluated totrue regardless of whether the timeout was triggered[.](#condvar-32.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[33](#condvar-33)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9925)
|
||
|
||
*Throws*: Timeout-related
|
||
exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) or any exception thrown by pred[.](#condvar-33.sentence-1)
|
||
|
||
[34](#condvar-34)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9930)
|
||
|
||
*Remarks*: If the function fails to meet the postcondition, terminate() is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#condvar-34.sentence-1)
|
||
|
||
[*Note [7](#condvar-note-7)*:
|
||
|
||
This can happen if the re-locking of the mutex throws an exception[.](#condvar-34.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:wait_for,condition_variable_)
|
||
|
||
`template<class Rep, class Period, class Predicate>
|
||
bool wait_for(unique_lock<mutex>& lock,
|
||
const chrono::duration<Rep, Period>& rel_time,
|
||
Predicate pred);
|
||
`
|
||
|
||
[35](#condvar-35)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9948)
|
||
|
||
*Preconditions*: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either
|
||
|
||
- [(35.1)](#condvar-35.1)
|
||
|
||
no other thread is waiting on this condition_variable object or
|
||
|
||
- [(35.2)](#condvar-35.2)
|
||
|
||
lock.mutex() returns the same value for each of the lock arguments
|
||
supplied by all concurrently waiting (via wait, wait_for, orwait_until) threads[.](#condvar-35.sentence-1)
|
||
|
||
[36](#condvar-36)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9962)
|
||
|
||
*Effects*: Equivalent to:return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred));
|
||
|
||
[37](#condvar-37)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9969)
|
||
|
||
[*Note [8](#condvar-note-8)*:
|
||
|
||
There is no blocking if pred() is initially true, even if the
|
||
timeout has already expired[.](#condvar-37.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[38](#condvar-38)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9975)
|
||
|
||
*Postconditions*: lock.owns_lock() is true and lock.mutex() is locked by the calling thread[.](#condvar-38.sentence-1)
|
||
|
||
[39](#condvar-39)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9980)
|
||
|
||
[*Note [9](#condvar-note-9)*:
|
||
|
||
The returned value indicates whether the predicate evaluates to true regardless of whether the timeout was triggered[.](#condvar-39.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[40](#condvar-40)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9986)
|
||
|
||
*Throws*: Timeout-related
|
||
exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) or any exception thrown by pred[.](#condvar-40.sentence-1)
|
||
|
||
[41](#condvar-41)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9991)
|
||
|
||
*Remarks*: If the function fails to meet the postcondition, terminate() is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#condvar-41.sentence-1)
|
||
|
||
[*Note [10](#condvar-note-10)*:
|
||
|
||
This can happen if the re-locking of the mutex throws an exception[.](#condvar-41.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
### [32.7.5](#condvarany) Class condition_variable_any [[thread.condition.condvarany]](thread.condition.condvarany)
|
||
|
||
#### [32.7.5.1](#condvarany.general) General [[thread.condition.condvarany.general]](thread.condition.condvarany.general)
|
||
|
||
[1](#condvarany.general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10004)
|
||
|
||
In [[thread.condition.condvarany]](#condvarany "32.7.5 Class condition_variable_any"),
|
||
template arguments for template parameters named Lock shall meet the [*Cpp17BasicLockable*](thread.req.lockable.basic#:Cpp17BasicLockable "32.2.5.2 Cpp17BasicLockable requirements [thread.req.lockable.basic]") requirements ([[thread.req.lockable.basic]](thread.req.lockable.basic "32.2.5.2 Cpp17BasicLockable requirements"))[.](#condvarany.general-1.sentence-1)
|
||
|
||
[*Note [1](#condvarany.general-note-1)*:
|
||
|
||
All of the standard
|
||
mutex types meet this requirement[.](#condvarany.general-1.sentence-2)
|
||
|
||
If a type other than one of the
|
||
standard mutex types or a unique_lock wrapper for a standard mutex type
|
||
is used with condition_variable_any, any
|
||
necessary synchronization is assumed to be in place with respect to the predicate associated
|
||
with the condition_variable_any instance[.](#condvarany.general-1.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:condition_variable_any)
|
||
|
||
namespace std {class condition_variable_any {public: condition_variable_any(); ~condition_variable_any();
|
||
|
||
condition_variable_any(const condition_variable_any&) = delete;
|
||
condition_variable_any& operator=(const condition_variable_any&) = delete; void notify_one() noexcept; void notify_all() noexcept; // [[thread.condvarany.wait]](#thread.condvarany.wait "32.7.5.2 Noninterruptible waits"), noninterruptible waitstemplate<class Lock>void wait(Lock& lock); template<class Lock, class Predicate>void wait(Lock& lock, Predicate pred); template<class Lock, class Clock, class Duration> cv_status wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time); template<class Lock, class Clock, class Duration, class Predicate>bool wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time,
|
||
Predicate pred); template<class Lock, class Rep, class Period> cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time); template<class Lock, class Rep, class Period, class Predicate>bool wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred); // [[thread.condvarany.intwait]](#thread.condvarany.intwait "32.7.5.3 Interruptible waits"), interruptible waitstemplate<class Lock, class Predicate>bool wait(Lock& lock, stop_token stoken, Predicate pred); template<class Lock, class Clock, class Duration, class Predicate>bool wait_until(Lock& lock, stop_token stoken, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred); template<class Lock, class Rep, class Period, class Predicate>bool wait_for(Lock& lock, stop_token stoken, const chrono::duration<Rep, Period>& rel_time, Predicate pred); };}
|
||
|
||
[ð](#lib:condition_variable_any,constructor)
|
||
|
||
`condition_variable_any();
|
||
`
|
||
|
||
[2](#condvarany.general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10067)
|
||
|
||
*Throws*: bad_alloc or system_error when an exception is
|
||
required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#condvarany.general-2.sentence-1)
|
||
|
||
[3](#condvarany.general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10072)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(3.1)](#condvarany.general-3.1)
|
||
|
||
resource_unavailable_try_again â if some non-memory resource
|
||
limitation prevents initialization[.](#condvarany.general-3.1.sentence-1)
|
||
|
||
- [(3.2)](#condvarany.general-3.2)
|
||
|
||
operation_not_permitted â if the thread does not have the
|
||
privilege to perform the operation[.](#condvarany.general-3.2.sentence-1)
|
||
|
||
[ð](#lib:condition_variable_any,destructor)
|
||
|
||
`~condition_variable_any();
|
||
`
|
||
|
||
[4](#condvarany.general-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10089)
|
||
|
||
*Preconditions*: There is no thread blocked on *this[.](#condvarany.general-4.sentence-1)
|
||
|
||
[*Note [2](#condvarany.general-note-2)*:
|
||
|
||
That is, all
|
||
threads have been notified; they can subsequently block on the lock specified in the
|
||
wait[.](#condvarany.general-4.sentence-2)
|
||
|
||
This relaxes the usual rules, which would have required all wait calls to happen before
|
||
destruction[.](#condvarany.general-4.sentence-3)
|
||
|
||
Only the notification to unblock the wait needs to happen before destruction[.](#condvarany.general-4.sentence-4)
|
||
|
||
Undefined behavior ensues if a thread waits on *this once the destructor has
|
||
been started, especially when the waiting threads are calling the wait functions in a loop or
|
||
using the overloads of wait, wait_for, or wait_until that take a predicate[.](#condvarany.general-4.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:notify_one,condition_variable_any)
|
||
|
||
`void notify_one() noexcept;
|
||
`
|
||
|
||
[5](#condvarany.general-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10110)
|
||
|
||
*Effects*: If any threads are blocked waiting for *this, unblocks one of those threads[.](#condvarany.general-5.sentence-1)
|
||
|
||
[ð](#lib:notify_all,condition_variable_any)
|
||
|
||
`void notify_all() noexcept;
|
||
`
|
||
|
||
[6](#condvarany.general-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10121)
|
||
|
||
*Effects*: Unblocks all threads that are blocked waiting for *this[.](#condvarany.general-6.sentence-1)
|
||
|
||
#### [32.7.5.2](#thread.condvarany.wait) Noninterruptible waits [[thread.condvarany.wait]](thread.condvarany.wait)
|
||
|
||
[ð](#lib:wait,condition_variable_any)
|
||
|
||
`template<class Lock>
|
||
void wait(Lock& lock);
|
||
`
|
||
|
||
[1](#thread.condvarany.wait-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10135)
|
||
|
||
*Effects*:
|
||
|
||
- [(1.1)](#thread.condvarany.wait-1.1)
|
||
|
||
Atomically calls lock.unlock() and blocks on *this[.](#thread.condvarany.wait-1.1.sentence-1)
|
||
|
||
- [(1.2)](#thread.condvarany.wait-1.2)
|
||
|
||
When unblocked, calls lock.lock() (possibly blocking on the lock) and returns[.](#thread.condvarany.wait-1.2.sentence-1)
|
||
|
||
- [(1.3)](#thread.condvarany.wait-1.3)
|
||
|
||
The function will unblock when signaled by a call to notify_one(),
|
||
a call to notify_all(), or spuriously[.](#thread.condvarany.wait-1.3.sentence-1)
|
||
|
||
[2](#thread.condvarany.wait-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10145)
|
||
|
||
*Postconditions*: lock is locked by the calling thread[.](#thread.condvarany.wait-2.sentence-1)
|
||
|
||
[3](#thread.condvarany.wait-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10149)
|
||
|
||
*Throws*: Nothing[.](#thread.condvarany.wait-3.sentence-1)
|
||
|
||
[4](#thread.condvarany.wait-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10153)
|
||
|
||
*Remarks*: If the function fails to meet the postcondition, terminate() is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#thread.condvarany.wait-4.sentence-1)
|
||
|
||
[*Note [1](#thread.condvarany.wait-note-1)*:
|
||
|
||
This can happen if the re-locking of the mutex throws an exception[.](#thread.condvarany.wait-4.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:wait,condition_variable_any_)
|
||
|
||
`template<class Lock, class Predicate>
|
||
void wait(Lock& lock, Predicate pred);
|
||
`
|
||
|
||
[5](#thread.condvarany.wait-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10169)
|
||
|
||
*Effects*: Equivalent to:while (!pred()) wait(lock);
|
||
|
||
[ð](#lib:wait_until,condition_variable_any)
|
||
|
||
`template<class Lock, class Clock, class Duration>
|
||
cv_status wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time);
|
||
`
|
||
|
||
[6](#thread.condvarany.wait-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10185)
|
||
|
||
*Effects*:
|
||
|
||
- [(6.1)](#thread.condvarany.wait-6.1)
|
||
|
||
Atomically calls lock.unlock() and blocks on *this[.](#thread.condvarany.wait-6.1.sentence-1)
|
||
|
||
- [(6.2)](#thread.condvarany.wait-6.2)
|
||
|
||
When unblocked, calls lock.lock() (possibly blocking on the lock) and returns[.](#thread.condvarany.wait-6.2.sentence-1)
|
||
|
||
- [(6.3)](#thread.condvarany.wait-6.3)
|
||
|
||
The function will unblock when signaled by a call to notify_one(), a call to notify_all(),
|
||
expiration of the absolute timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified by abs_time,
|
||
or spuriously[.](#thread.condvarany.wait-6.3.sentence-1)
|
||
|
||
- [(6.4)](#thread.condvarany.wait-6.4)
|
||
|
||
If the function exits via an exception, lock.lock() is called prior to exiting the function[.](#thread.condvarany.wait-6.4.sentence-1)
|
||
|
||
[7](#thread.condvarany.wait-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10204)
|
||
|
||
*Postconditions*: lock is locked by the calling thread[.](#thread.condvarany.wait-7.sentence-1)
|
||
|
||
[8](#thread.condvarany.wait-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10208)
|
||
|
||
*Returns*: cv_status::timeout if
|
||
the absolute timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified by abs_time expired,
|
||
otherwise cv_status::no_timeout[.](#thread.condvarany.wait-8.sentence-1)
|
||
|
||
[9](#thread.condvarany.wait-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10214)
|
||
|
||
*Throws*: Timeout-related
|
||
exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))[.](#thread.condvarany.wait-9.sentence-1)
|
||
|
||
[10](#thread.condvarany.wait-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10219)
|
||
|
||
*Remarks*: If the function fails to meet the postcondition, terminate() is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#thread.condvarany.wait-10.sentence-1)
|
||
|
||
[*Note [2](#thread.condvarany.wait-note-2)*:
|
||
|
||
This can happen if the re-locking of the mutex throws an exception[.](#thread.condvarany.wait-10.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:wait_for,condition_variable_any)
|
||
|
||
`template<class Lock, class Rep, class Period>
|
||
cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time);
|
||
`
|
||
|
||
[11](#thread.condvarany.wait-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10235)
|
||
|
||
*Effects*: Equivalent to:return wait_until(lock, chrono::steady_clock::now() + rel_time);
|
||
|
||
[12](#thread.condvarany.wait-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10242)
|
||
|
||
*Postconditions*: lock is locked by the calling thread[.](#thread.condvarany.wait-12.sentence-1)
|
||
|
||
[13](#thread.condvarany.wait-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10246)
|
||
|
||
*Returns*: cv_status::timeout if
|
||
the relative timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified by rel_time expired,
|
||
otherwise cv_status::no_timeout[.](#thread.condvarany.wait-13.sentence-1)
|
||
|
||
[14](#thread.condvarany.wait-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10252)
|
||
|
||
*Throws*: Timeout-related
|
||
exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))[.](#thread.condvarany.wait-14.sentence-1)
|
||
|
||
[15](#thread.condvarany.wait-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10257)
|
||
|
||
*Remarks*: If the function fails to meet the postcondition, terminate is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#thread.condvarany.wait-15.sentence-1)
|
||
|
||
[*Note [3](#thread.condvarany.wait-note-3)*:
|
||
|
||
This can happen if the re-locking of the mutex throws an exception[.](#thread.condvarany.wait-15.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:wait_until,condition_variable_any_)
|
||
|
||
`template<class Lock, class Clock, class Duration, class Predicate>
|
||
bool wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
|
||
`
|
||
|
||
[16](#thread.condvarany.wait-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10273)
|
||
|
||
*Effects*: Equivalent to:while (!pred())if (wait_until(lock, abs_time) == cv_status::timeout)return pred();return true;
|
||
|
||
[17](#thread.condvarany.wait-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10283)
|
||
|
||
[*Note [4](#thread.condvarany.wait-note-4)*:
|
||
|
||
There is no blocking if pred() is initially true, or
|
||
if the timeout has already expired[.](#thread.condvarany.wait-17.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[18](#thread.condvarany.wait-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10289)
|
||
|
||
[*Note [5](#thread.condvarany.wait-note-5)*:
|
||
|
||
The returned value indicates whether the predicate evaluates to true regardless of whether the timeout was triggered[.](#thread.condvarany.wait-18.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:wait_for,condition_variable_any_)
|
||
|
||
`template<class Lock, class Rep, class Period, class Predicate>
|
||
bool wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred);
|
||
`
|
||
|
||
[19](#thread.condvarany.wait-19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10303)
|
||
|
||
*Effects*: Equivalent to:return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred));
|
||
|
||
#### [32.7.5.3](#thread.condvarany.intwait) Interruptible waits [[thread.condvarany.intwait]](thread.condvarany.intwait)
|
||
|
||
[1](#thread.condvarany.intwait-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10313)
|
||
|
||
The following wait functions will be notified
|
||
when there is a stop request on the passed stop_token[.](#thread.condvarany.intwait-1.sentence-1)
|
||
|
||
In that case the functions return immediately,
|
||
returning false if the predicate evaluates to false[.](#thread.condvarany.intwait-1.sentence-2)
|
||
|
||
[ð](#thread.condvarany.intwait-itemdecl:1)
|
||
|
||
`template<class Lock, class Predicate>
|
||
bool wait(Lock& lock, stop_token stoken, Predicate pred);
|
||
`
|
||
|
||
[2](#thread.condvarany.intwait-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10325)
|
||
|
||
*Effects*: Registers for the duration of this call *this to get notified on a stop request on stoken during this call and then equivalent to:while (!stoken.stop_requested()) {if (pred())return true;
|
||
wait(lock);}return pred();
|
||
|
||
[3](#thread.condvarany.intwait-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10339)
|
||
|
||
[*Note [1](#thread.condvarany.intwait-note-1)*:
|
||
|
||
The returned value indicates whether the predicate evaluated totrue regardless of whether there was a stop request[.](#thread.condvarany.intwait-3.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[4](#thread.condvarany.intwait-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10345)
|
||
|
||
*Postconditions*: lock is locked by the calling thread[.](#thread.condvarany.intwait-4.sentence-1)
|
||
|
||
[5](#thread.condvarany.intwait-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10349)
|
||
|
||
*Throws*: Any exception thrown by pred[.](#thread.condvarany.intwait-5.sentence-1)
|
||
|
||
[6](#thread.condvarany.intwait-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10353)
|
||
|
||
*Remarks*: If the function fails to meet the postcondition,terminate is called ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#thread.condvarany.intwait-6.sentence-1)
|
||
|
||
[*Note [2](#thread.condvarany.intwait-note-2)*:
|
||
|
||
This can happen if the re-locking of the mutex throws an exception[.](#thread.condvarany.intwait-6.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#thread.condvarany.intwait-itemdecl:2)
|
||
|
||
`template<class Lock, class Clock, class Duration, class Predicate>
|
||
bool wait_until(Lock& lock, stop_token stoken,
|
||
const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
|
||
`
|
||
|
||
[7](#thread.condvarany.intwait-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10369)
|
||
|
||
*Effects*: Registers for the duration of this call *this to get notified on a stop request on stoken during this call and then equivalent to:while (!stoken.stop_requested()) {if (pred())return true; if (wait_until(lock, abs_time) == cv_status::timeout)return pred();}return pred();
|
||
|
||
[8](#thread.condvarany.intwait-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10384)
|
||
|
||
[*Note [3](#thread.condvarany.intwait-note-3)*:
|
||
|
||
There is no blocking if pred() is initially true,stoken.stop_requested() was already true or the timeout has already expired[.](#thread.condvarany.intwait-8.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[9](#thread.condvarany.intwait-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10391)
|
||
|
||
[*Note [4](#thread.condvarany.intwait-note-4)*:
|
||
|
||
The returned value indicates whether the predicate evaluated to true regardless of whether the timeout was triggered or a stop request was made[.](#thread.condvarany.intwait-9.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[10](#thread.condvarany.intwait-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10397)
|
||
|
||
*Postconditions*: lock is locked by the calling thread[.](#thread.condvarany.intwait-10.sentence-1)
|
||
|
||
[11](#thread.condvarany.intwait-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10401)
|
||
|
||
*Throws*: Timeout-related exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")),
|
||
or any exception thrown by pred[.](#thread.condvarany.intwait-11.sentence-1)
|
||
|
||
[12](#thread.condvarany.intwait-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10406)
|
||
|
||
*Remarks*: If the function fails to meet the postcondition,terminate is called ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#thread.condvarany.intwait-12.sentence-1)
|
||
|
||
[*Note [5](#thread.condvarany.intwait-note-5)*:
|
||
|
||
This can happen if the re-locking of the mutex throws an exception[.](#thread.condvarany.intwait-12.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#thread.condvarany.intwait-itemdecl:3)
|
||
|
||
`template<class Lock, class Rep, class Period, class Predicate>
|
||
bool wait_for(Lock& lock, stop_token stoken,
|
||
const chrono::duration<Rep, Period>& rel_time, Predicate pred);
|
||
`
|
||
|
||
[13](#thread.condvarany.intwait-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10422)
|
||
|
||
*Effects*: Equivalent to:return wait_until(lock, std::move(stoken), chrono::steady_clock::now() + rel_time,
|
||
std::move(pred));
|