Files
2025-10-25 03:02:53 +03:00

485 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[thread.condition.condvar]
# 32 Concurrency support library [[thread]](./#thread)
## 32.7 Condition variables [[thread.condition]](thread.condition#condvar)
### 32.7.4 Class condition_variable [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.3Native handles") native_handle_type native_handle(); // see [[thread.req.native]](thread.req.native "32.2.3Native handles")};}
[1](#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.2Properties of classes"))[.](#1.sentence-1)
[🔗](#lib:condition_variable,constructor)
`condition_variable();
`
[2](#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.2Exceptions"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9631)
*Error conditions*:
- [(3.1)](#3.1)
resource_unavailable_try_again — if some non-memory resource
limitation prevents initialization[.](#3.sentence-1)
[🔗](#lib:condition_variable,destructor)
`~condition_variable();
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9645)
*Preconditions*: There is no thread blocked on *this[.](#4.sentence-1)
[*Note [1](#note-1)*:
That is, all
threads have been notified; they can subsequently block on the lock specified in the
wait[.](#4.sentence-2)
This relaxes the usual rules, which would have required all wait calls to happen before
destruction[.](#4.sentence-3)
Only the notification to unblock the wait needs to happen before destruction[.](#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[.](#4.sentence-5)
— *end note*]
[🔗](#lib:notify_one,condition_variable)
`void notify_one() noexcept;
`
[5](#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[.](#5.sentence-1)
[🔗](#lib:notify_all,condition_variable)
`void notify_all() noexcept;
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9677)
*Effects*: Unblocks all threads that are blocked waiting for *this[.](#6.sentence-1)
[🔗](#lib:wait,condition_variable)
`void wait(unique_lock<mutex>& lock);
`
[7](#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)](#7.1)
no other thread is waiting on this condition_variable object or
- [(7.2)](#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[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9699)
*Effects*:
- [(8.1)](#8.1)
Atomically calls lock.unlock() and blocks on *this[.](#8.1.sentence-1)
- [(8.2)](#8.2)
When unblocked, calls lock.lock() (possibly blocking on the lock), then returns[.](#8.2.sentence-1)
- [(8.3)](#8.3)
The function will unblock when signaled by a call to notify_one() or a call to notify_all(), or spuriously[.](#8.3.sentence-1)
[9](#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[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9714)
*Throws*: Nothing[.](#10.sentence-1)
[11](#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.2The std::terminate function"))[.](#11.sentence-1)
[*Note [2](#note-2)*:
This can happen if the re-locking of the mutex throws an exception[.](#11.sentence-2)
— *end note*]
[🔗](#lib:wait,condition_variable_)
`template<class Predicate>
void wait(unique_lock<mutex>& lock, Predicate pred);
`
[12](#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)](#12.1)
no other thread is waiting on this condition_variable object or
- [(12.2)](#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[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9745)
*Effects*: Equivalent to:while (!pred()) wait(lock);
[14](#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[.](#14.sentence-1)
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9758)
*Throws*: Any exception thrown by pred[.](#15.sentence-1)
[16](#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.2The std::terminate function"))[.](#16.sentence-1)
[*Note [3](#note-3)*:
This can happen if the re-locking of the mutex throws an exception[.](#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](#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)](#17.1)
no other thread is waiting on this condition_variable object or
- [(17.2)](#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[.](#17.sentence-1)
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9790)
*Effects*:
- [(18.1)](#18.1)
Atomically calls lock.unlock() and blocks on *this[.](#18.1.sentence-1)
- [(18.2)](#18.2)
When unblocked, calls lock.lock() (possibly blocking on the lock), then returns[.](#18.2.sentence-1)
- [(18.3)](#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.4Timing specifications")) specified by abs_time,
or spuriously[.](#18.3.sentence-1)
- [(18.4)](#18.4)
If the function exits via an exception, lock.lock() is called prior to exiting the function[.](#18.4.sentence-1)
[19](#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[.](#19.sentence-1)
[20](#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.4Timing specifications")) specified by abs_time expired,
otherwise cv_status::no_timeout[.](#20.sentence-1)
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9819)
*Throws*: Timeout-related
exceptions ([[thread.req.timing]](thread.req.timing "32.2.4Timing specifications"))[.](#21.sentence-1)
[22](#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.2The std::terminate function"))[.](#22.sentence-1)
[*Note [4](#note-4)*:
This can happen if the re-locking of the mutex throws an exception[.](#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](#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)](#23.1)
no other thread is waiting on this condition_variable object or
- [(23.2)](#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[.](#23.sentence-1)
[24](#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](#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[.](#25.sentence-1)
[26](#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.4Timing specifications")) specified by rel_time expired,
otherwise cv_status::no_timeout[.](#26.sentence-1)
[27](#27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9870)
*Throws*: Timeout-related
exceptions ([[thread.req.timing]](thread.req.timing "32.2.4Timing specifications"))[.](#27.sentence-1)
[28](#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.2The std::terminate function"))[.](#28.sentence-1)
[*Note [5](#note-5)*:
This can happen if the re-locking of the mutex throws an exception[.](#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](#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)](#29.1)
no other thread is waiting on this condition_variable object or
- [(29.2)](#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[.](#29.sentence-1)
[30](#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](#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[.](#31.sentence-1)
[32](#32)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9919)
[*Note [6](#note-6)*:
The returned value indicates whether the predicate evaluated totrue regardless of whether the timeout was triggered[.](#32.sentence-1)
— *end note*]
[33](#33)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9925)
*Throws*: Timeout-related
exceptions ([[thread.req.timing]](thread.req.timing "32.2.4Timing specifications")) or any exception thrown by pred[.](#33.sentence-1)
[34](#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.2The std::terminate function"))[.](#34.sentence-1)
[*Note [7](#note-7)*:
This can happen if the re-locking of the mutex throws an exception[.](#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](#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)](#35.1)
no other thread is waiting on this condition_variable object or
- [(35.2)](#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[.](#35.sentence-1)
[36](#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](#37)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9969)
[*Note [8](#note-8)*:
There is no blocking if pred() is initially true, even if the
timeout has already expired[.](#37.sentence-1)
— *end note*]
[38](#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[.](#38.sentence-1)
[39](#39)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9980)
[*Note [9](#note-9)*:
The returned value indicates whether the predicate evaluates to true regardless of whether the timeout was triggered[.](#39.sentence-1)
— *end note*]
[40](#40)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L9986)
*Throws*: Timeout-related
exceptions ([[thread.req.timing]](thread.req.timing "32.2.4Timing specifications")) or any exception thrown by pred[.](#40.sentence-1)
[41](#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.2The std::terminate function"))[.](#41.sentence-1)
[*Note [10](#note-10)*:
This can happen if the re-locking of the mutex throws an exception[.](#41.sentence-2)
— *end note*]