[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));
