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
. Class
condition_variable provides a condition variable that can only
wait on an object of type
unique_lock<mutex>, allowing maximum efficiency on some
platforms
. Class
condition_variable_any provides a general condition variable
that can wait on objects of user-supplied lock types
.
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; native_handle_type native_handle(); };
}
The class
condition_variable shall be a standard-layout class (Clause
[class])
. condition_variable();
Effects: Constructs an object of type
condition_variable. Error conditions:
resource_unavailable_try_again — if some non-memory resource
limitation prevents initialization
.
~condition_variable();
Requires: There shall be no thread blocked on
*this. [
Note: That is, all
threads shall have been notified; they may subsequently block on the lock specified in the
wait
. This relaxes the usual rules, which would have required all wait calls to happen before
destruction
. Only the notification to unblock the wait must happen before destruction
. The user must take care to ensure that no threads wait 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
. —
end note ]
Effects: Destroys the object
. void notify_one() noexcept;
Effects: If any threads are blocked waiting for
*this, unblocks one of those threads
. void notify_all() noexcept;
Effects: Unblocks all threads that are blocked waiting for
*this. void wait(unique_lock<mutex>& lock);
Requires: lock.owns_lock() is
true and
lock.mutex()
is locked by the calling thread, and either
Effects:
Atomically calls
lock.unlock() and blocks on
*this.When unblocked, calls
lock.lock() (possibly blocking on the lock), then returns
.The function will unblock when signaled by a call to
notify_one()
or a call to
notify_all(), or spuriously
.
Remarks:
If the function fails to meet the postcondition,
terminate()
shall be called (
[except.terminate])
. [
Note: This can happen if the re-locking of the mutex throws an exception
. —
end note ]
Postconditions: lock.owns_lock() is
true and
lock.mutex()
is locked by the calling thread
. template <class Predicate>
void wait(unique_lock<mutex>& lock, Predicate pred);
Requires: lock.owns_lock() is true and lock.mutex() is
locked by the calling thread, and either
Effects: Equivalent to:
while (!pred())
wait(lock);
Remarks:
If the function fails to meet the postcondition,
terminate()
shall be called (
[except.terminate])
. [
Note: This can happen if the re-locking of the mutex throws an exception
. —
end note ]
Postconditions: lock.owns_lock() is
true and
lock.mutex()
is locked by the calling thread
. Throws: Any exception thrown by
pred. template <class Clock, class Duration>
cv_status wait_until(unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& abs_time);
Requires: lock.owns_lock() is
true and
lock.mutex()
is locked by the calling thread, and either
Effects:
Atomically calls
lock.unlock() and blocks on
*this.When unblocked, calls
lock.lock() (possibly blocking on the lock), then returns
.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]) specified by
abs_time,
or spuriously
.If the function exits via an exception,
lock.lock() shall be called prior to exiting the function
.
Remarks:
If the function fails to meet the postcondition,
terminate()
shall be called (
[except.terminate])
. [
Note: This can happen if the re-locking of the mutex throws an exception
. —
end note ]
Postconditions: lock.owns_lock() is
true and
lock.mutex()
is locked by the calling thread
. Returns: cv_status::timeout if
the absolute timeout (
[thread.req.timing]) specified by
abs_time expired,
otherwise
cv_status::no_timeout. template <class Rep, class Period>
cv_status wait_for(unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& rel_time);
Requires: lock.owns_lock() is
true and
lock.mutex()
is locked by the calling thread, and either
Effects: Equivalent to:
return wait_until(lock, chrono::steady_clock::now() + rel_time);
Returns: cv_status::timeout if
the relative timeout (
[thread.req.timing]) specified by
rel_time expired,
otherwise
cv_status::no_timeout. Remarks:
If the function fails to meet the postcondition,
terminate()
shall be called (
[except.terminate])
. [
Note: This can happen if the re-locking of the mutex throws an exception
. —
end note ]
Postconditions: lock.owns_lock() is
true and
lock.mutex()
is locked by the calling thread
. template <class Clock, class Duration, class Predicate>
bool wait_until(unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& abs_time,
Predicate pred);
Requires: lock.owns_lock() is true and lock.mutex() is
locked by the calling thread, and either
Effects: Equivalent to:
while (!pred())
if (wait_until(lock, abs_time) == cv_status::timeout)
return pred();
return true;
Remarks:
If the function fails to meet the postcondition,
terminate()
shall be called (
[except.terminate])
. [
Note: This can happen if the re-locking of the mutex throws an exception
. —
end note ]
Postconditions: lock.owns_lock() is
true and
lock.mutex()
is locked by the calling thread
. [
Note: The returned value indicates whether the predicate evaluated to
true regardless of whether the timeout was triggered
. —
end note ]
template <class Rep, class Period, class Predicate>
bool wait_for(unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& rel_time,
Predicate pred);
Requires: lock.owns_lock() is
true and
lock.mutex()
is locked by the calling thread, and either
Effects: Equivalent to:
return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred));
[
Note: There is no blocking if
pred() is initially
true, even if the
timeout has already expired
. —
end note ]
Remarks:
If the function fails to meet the postcondition,
terminate()
shall be called (
[except.terminate])
. [
Note: This can happen if the re-locking of the mutex throws an exception
. —
end note ]
Postconditions: lock.owns_lock() is
true and
lock.mutex()
is locked by the calling thread
. [
Note: The returned value indicates whether the predicate evaluates to
true
regardless of whether the timeout was triggered
. —
end note ]
[
Note: All of the standard
mutex types meet this requirement
. If a
Lock 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, the user must ensure that any
necessary synchronization is in place with respect to the predicate associated
with the
condition_variable_any instance
. —
end note ]
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;
template <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);
};
}
condition_variable_any();
Effects: Constructs an object of type
condition_variable_any. Error conditions:
resource_unavailable_try_again — if some non-memory resource
limitation prevents initialization
. operation_not_permitted — if the thread does not have the
privilege to perform the operation
.
~condition_variable_any();
Requires: There shall be no thread blocked on
*this. [
Note: That is, all
threads shall have been notified; they may subsequently block on the lock specified in the
wait
. This relaxes the usual rules, which would have required all wait calls to happen before
destruction
. Only the notification to unblock the wait must happen before destruction
. The user must take care to ensure that no threads wait 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
. —
end note ]
Effects: Destroys the object
. void notify_one() noexcept;
Effects: If any threads are blocked waiting for
*this, unblocks one of those threads
. void notify_all() noexcept;
Effects: Unblocks all threads that are blocked waiting for
*this. template <class Lock>
void wait(Lock& lock);
[
Note: If any of the
wait functions exits via an exception, it is
unspecified whether the
Lock is held
. One can use a
Lock type
that allows to query that, such as the
unique_lock wrapper
. —
end note ]
Effects:
Atomically calls
lock.unlock() and blocks on
*this.When unblocked, calls
lock.lock() (possibly blocking on the lock) and returns
.The function will unblock when signaled by a call to
notify_one(),
a call to
notify_all(), or spuriously
.
Remarks:
If the function fails to meet the postcondition,
terminate()
shall be called (
[except.terminate])
. [
Note: This can happen if the re-locking of the mutex throws an exception
. —
end note ]
Postconditions: lock is locked by the calling thread
. template <class Lock, class Predicate>
void wait(Lock& lock, Predicate pred);
Effects: Equivalent to:
while (!pred())
wait(lock);
template <class Lock, class Clock, class Duration>
cv_status wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time);
Effects:Atomically calls
lock.unlock() and blocks on
*this.When unblocked, calls
lock.lock() (possibly blocking on the lock) and returns
.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]) specified by
abs_time,
or spuriously
.If the function exits via an exception,
lock.lock() shall be called prior to exiting the function
.
Remarks:
If the function fails to meet the postcondition,
terminate()
shall be called (
[except.terminate])
. [
Note: This can happen if the re-locking of the mutex throws an exception
. —
end note ]
Postconditions: lock is locked by the calling thread
. Returns: cv_status::timeout if
the absolute timeout (
[thread.req.timing]) specified by
abs_time expired,
otherwise
cv_status::no_timeout. template <class Lock, class Rep, class Period>
cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time);
Effects: Equivalent to:
return wait_until(lock, chrono::steady_clock::now() + rel_time);
Returns: cv_status::timeout if
the relative timeout (
[thread.req.timing]) specified by
rel_time expired,
otherwise
cv_status::no_timeout. Remarks:
If the function fails to meet the postcondition,
terminate()
shall be called (
[except.terminate])
. [
Note: This can happen if the re-locking of the mutex throws an exception
. —
end note ]
Postconditions: lock is locked by the calling thread
. template <class Lock, class Clock, class Duration, class Predicate>
bool wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
Effects: Equivalent to:
while (!pred())
if (wait_until(lock, abs_time) == cv_status::timeout)
return pred();
return true;
[
Note: There is no blocking if
pred() is initially
true, or
if the timeout has already expired
. —
end note ]
[
Note: The returned value indicates whether the predicate evaluates to
true
regardless of whether the timeout was triggered
. —
end note ]
template <class Lock, class Rep, class Period, class Predicate>
bool wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred);
Effects: Equivalent to:
return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred));