Namespaces
Variants

std::condition_variable_any:: wait_until

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
template < class Lock, class Clock, class Duration >

std:: cv_status
wait_until ( Lock & lock,

const std:: chrono :: time_point < Clock, Duration > & abs_time ) ;
(1) (C++11 起)
template < class Lock, class Clock, class Duration, class Predicate >

bool wait_until ( Lock & lock,
const std:: chrono :: time_point < Clock, Duration > & abs_time,

Predicate pred ) ;
(2) (C++11 起)
template < class Lock, class Clock, class Duration, class Predicate >

bool wait_until ( Lock & lock, std:: stop_token stoken,
const std:: chrono :: time_point < Clock, Duration > & abs_time,

Predicate pred ) ;
(3) (C++20 起)

wait_until 使当前线程阻塞,直到条件变量被通知、指定持续时间已用完或发生伪唤醒。可选择性地提供 pred 来检测伪唤醒。

1) 原子地调用 lock. unlock ( ) 并在 * this 上阻塞。
当执行 notify_all() notify_one() ,或到达 abs_time 时,线程将被解除阻塞。也可能出现伪唤醒。
当解除阻塞时,调用 lock. lock ( ) (可能会在锁上阻塞),然后返回。
2,3) 等待特定条件变为真,可用于忽略虚假唤醒。
2) 等价于 while ( ! pred ( ) )
if ( wait_until ( lock, abs_time ) == std:: cv_status :: timeout )
return pred ( ) ;
return true ;
3) 在此调用期间注册 * this ,以便在 stoken 关联的停止状态收到停止请求时获得通知;此时等效于 while ( ! stoken. stop_requested ( ) )
{
if ( pred ( ) )
return true ;
if ( wait_until ( lock, abs_time ) == std:: cv_status :: timeout )
return pred ( ) ;
}
return pred ( ) ;

wait_until 返回后, lock 会被调用线程锁定。若无法满足此后置条件 [1] ,则调用 std::terminate

  1. 这种情况可能发生在互斥锁重新加锁时抛出异常的情况下。

目录

参数

lock - 必须由调用线程锁定的锁
stoken - 用于注册中断的停止令牌
abs_time - 等待到期的时间点
pred - 用于检查等待是否可完成的谓词
类型要求
-
Lock 必须满足 BasicLockable 的要求。
-
Predicate 必须满足 FunctionObject 的要求。
-
pred ( ) 必须是合法表达式,且其类型和值类别必须满足 BooleanTestable 要求。

返回值

1) std:: cv_status :: timeout 若已达到 abs_time ,否则为 std:: cv_status :: no_timeout
2,3) 返回给调用方前 pred ( ) 的最新结果。

异常

1) 超时相关异常。
2,3) 与超时相关的异常,以及由 pred 抛出的任何异常。

注释

标准建议使用与 abs_time 绑定的时钟来测量时间;该时钟不要求是单调时钟。如果时钟被不连续调整,此函数的行为不作保证,但现有实现会将 abs_time Clock 转换为 std::chrono::system_clock 并委托给POSIX pthread_cond_timedwait ,因此等待会遵循系统时钟的调整,但不会遵循用户提供的 Clock 的调整。在任何情况下,由于调度或资源竞争延迟,该函数的实际等待时间可能超过 abs_time 所指定的时间点。

即使使用的时钟是 std::chrono::steady_clock 或其他单调时钟,系统时钟调整仍可能引发伪唤醒。

notify_one() / notify_all() 的效果以及 wait() / wait_for() / wait_until() 的三个原子操作部分(解锁+等待、唤醒和加锁)的发生顺序,构成一个可被视为原子变量 修改顺序 的单一全序:该顺序特定于此条件变量。这使得例如 notify_one() 不可能被延迟,并解除那些恰好在 notify_one() 调用之后才开始等待的线程的阻塞状态。

示例

#include <chrono>
#include <condition_variable>
#include <iostream>
#include <thread>
std::condition_variable_any cv;
std::mutex cv_m; // 此互斥锁用于三个目的:
                 // 1) 同步对 i 的访问
                 // 2) 同步对 std::cerr 的访问
                 // 3) 用于条件变量 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();
}

可能的输出:

Waiting...
Waiting...
Waiting...
Notifying...
Notifying again...
...finished waiting. i == 1
...finished waiting. i == 1
...finished waiting. i == 1

缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的C++标准。

缺陷报告 应用于 发布时的行为 正确行为
LWG 2093 C++11 规范中缺少超时相关异常说明 明确提及这些异常
LWG 2114
( P2167R3 )
C++11 bool 转换能力过弱,无法满足实现预期 强化了相关要求
LWG 2135 C++11 lock. lock ( ) 抛出异常时的行为不明确 在此情况下调用 std::terminate

参见

阻塞当前线程,直到条件变量被唤醒
(公开成员函数)
wait_until
阻塞当前线程,直到条件变量被唤醒或到达指定时间点
(公开成员函数)