32 Thread support library [thread]

32.6 Condition variables [thread.condition]

32.6.4 Class condition_­variable_­any [thread.condition.condvarany]

A Lock type shall meet the Cpp17BasicLockable requirements ([thread.req.lockable.basic]).
[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 should 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;

    // [thread.condvarany.wait], noninterruptible waits
    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);

    // [thread.condvarany.intwait], interruptible waits
    template<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);
  };
}
condition_variable_any();
Throws: bad_­alloc or system_­error when an exception is required ([thread.req.exception]).
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();
Preconditions: There is no thread blocked on *this.
[Note
:
That is, all threads have been notified; they could 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 needs to happen before destruction.
The user should 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
]
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.

32.6.4.1 Noninterruptible waits [thread.condvarany.wait]

template<class Lock> void wait(Lock& lock);
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() is 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.
Throws: Nothing.
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() is called prior to exiting the function.
Remarks: If the function fails to meet the postcondition, terminate() is 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.
Throws: Timeout-related exceptions ([thread.req.timing]).
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() is 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.
Throws: Timeout-related exceptions ([thread.req.timing]).
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));

32.6.4.2 Interruptible waits [thread.condvarany.intwait]

The following wait functions will be notified when there is a stop request on the passed stop_­token.
In that case the functions return immediately, returning false if the predicate evaluates to false.
template<class Lock, class Predicate> bool wait(Lock& lock, stop_token stoken, Predicate pred);
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();
[Note
:
The returned value indicates whether the predicate evaluated to true regardless of whether there was a stop request.
— end note
]
Postconditions: lock is locked by the calling thread.
Remarks: If the function fails to meet the postcondition, terminate is called ([except.terminate]).
[Note
:
This can happen if the re-locking of the mutex throws an exception.
— end note
]
Throws: Any exception thrown by 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);
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 (cv.wait_until(lock, abs_time) == cv_status::timeout)
    return pred();
}
return pred();
[Note
:
There is no blocking if pred() is initially true, stoken.stop_­requested() was already true or the timeout has already expired.
— end note
]
[Note
:
The returned value indicates whether the predicate evaluated to true regardless of whether the timeout was triggered or a stop request was made.
— end note
]
Postconditions: lock is locked by the calling thread.
Remarks: If the function fails to meet the postcondition, terminate is called ([except.terminate]).
[Note
:
This can happen if the re-locking of the mutex throws an exception.
— end note
]
Throws: Timeout-related exceptions ([thread.req.timing]), or any exception thrown by 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);
Effects: Equivalent to:
return wait_until(lock, std::move(stoken), chrono::steady_clock::now() + rel_time,
                  std::move(pred));