std::condit...ny::wait_for(3)
std::condition_variable_any::wait_for β¨π
okay so this is from the C++ Standard Libary manual (yes, βLibaryβ, iconic typo energy), page std::condit...ny::wait_for(3). bestie, this one is all about making a thread chill until something happens, and the details matter fr fr. π«Ά
π NAME π
std::condition_variable_any::wait_for β std::condition_variable_any::wait_for
πΈ Synopsis πΈ
three overloads, all iconic, with the C++11/C++20 timestamps kept exactly:
Overload 1 (since C++11):
template< class Lock, class Rep, class Period >
std::cv_status wait_for( Lock& lock,
const std::chrono::duration<Rep, Period>& rel_time );
Overload 2 (since C++11):
template< class Lock, class Rep, class Period, class Predicate >
bool wait_for( Lock& lock, const std::chrono::duration<Rep, Period>& rel_time,
Predicate pred );
Overload 3 (since C++20):
template< class Lock, class Rep, class Period, class Predicate >
bool wait_for( Lock& lock, std::stop_token stoken,
const std::chrono::duration<Rep, Period>& rel_time,
Predicate pred );
wait_for causes the current thread to block until the condition variable is notified, the given duration has been elapsed, or a spurious wakeup occurs. pred can be optionally provided to detect spurious wakeup. the way thatβs the whole vibe π
- 1) Equivalent to
return wait_until(lock, std::chrono::steady_clock::now() + rel_time);. - 2,3) Waiting for a specific condition to become true, can be used to ignore spurious awakenings.
- 2) Equivalent to
return wait_until(lock, std::chrono::steady_clock::now() + rel_time, std::move(pred));. - 3) Registers
*thisfor the duration of this call, to be notified if a stop request is made onstoken's associated stop-state; it is then equivalent toreturn wait_until(lock, std::move(stoken), std::chrono::steady_clock::now() + rel_time, std::move(pred));.
Right afterwait_forreturns,lockis locked by the calling thread. If this postcondition cannot be satisfied^[1], callsstd::terminate.
^[1] β This can happen if the re-locking of the mutex throws an exception. do not ignore this one, bestie π
π«Ά Parameters π«Ά
lockβ a lock that must be locked by the calling threadstokenβ a stop token to register interruption forrel_timeβ the maximum duration to waitpredβ the predicate to check whether the waiting can be completed
π§ Type requirements π§
Lockmust meet the requirements ofBasicLockable.Predicatemust meet the requirements ofFunctionObject.
π Return value π
- 1)
std::cv_status::timeoutifrel_timehas been elapsed since the beginning of this call, otherwisestd::cv_status::no_timeout. - 2,3) The latest result of
pred()before returning to the caller.
π Exceptions π
- 1) Timeout-related exceptions.
- 2,3) Timeout-related exceptions, and any exception thrown by
pred.
π Notes π
Even if notified under lock, overload (1) makes no guarantees about the state of the associated predicate when returning due to timeout. subtle but important, okay? π
The effects of notify_one()/notify_all() and each of the three atomic parts of wait()/wait_for()/wait_until() (unlock+wait, wakeup, and lock) take place in a single total order that can be viewed as modification order of an atomic variable: the order is specific to this individual condition variable. This makes it impossible for notify_one() to, for example, be delayed and unblock a thread that started waiting just after the call to notify_one() was made. thatβs the whole βno cutting the lineβ rule, periodt β¨
π Example π
run this code, bestie β itβs giving three waiters and one signaler:
// Run this code
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <thread>
std::condition_variable_any cv;
std::mutex cv_m; // This mutex is used for three purposes:
// 1) to synchronize accesses to i
// 2) to synchronize accesses to std::cerr
// 3) for the condition variable cv
int i = 0;
void waits()
{
std::unique_lock<std::mutex> lk(cv_m);
std::cerr << "Waiting... \n";
cv.wait(lk, []{ return i == 1; });
std::cerr << "...finished waiting. i == 1\n";
}
void signals()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lk(cv_m);
std::cerr << "Notifying...\n";
}
cv.notify_all();
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lk(cv_m);
i = 1;
std::cerr << "Notifying again...\n";
}
cv.notify_all();
}
int main()
{
std::thread t1(waits), t2(waits), t3(waits), t4(signals);
t1.join();
t2.join();
t3.join();
t4.join();
}
β¨ Possible output β¨
Waiting...
Waiting...
Waiting...
Notifying...
Notifying again...
...finished waiting. i == 1
...finished waiting. i == 1
...finished waiting. i == 1
π₯ Defect reports π₯
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
- DR
LWG 2093, applied to C++11 β behavior as published: timeout-related exceptions were missing in the specification; correct behavior: mentions these exceptions. - DR
LWG 2135, applied to C++11 β behavior as published: the behavior was unclear iflock.lock()throws an exception; correct behavior: callsstd::terminatein this case.
π¦ See also π¦
waitβ blocks the current thread until the condition variable is awakened (public member function)wait_untilβ blocks the current thread until the condition variable is awakened or until specified time point has been reached (public member function)
π Hidden category π
- Pages with unreviewed LWG DR marker
source/version/date sign-off: cppreference.com Β· 2024.06.10 Β· std::condit...ny::wait_for(3) β bye bestie, go wait on something gorgeous πβ¨
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms