公有成员函数
<condition_variable>

std::condition_variable::wait_until

无条件 (1)
template <class Clock, class Duration>  cv_status wait_until (unique_lock<mutex>& lck,                        const chrono::time_point<Clock,Duration>& abs_time);
谓词 (2)
template <class Clock, class Duration, class Predicate>       bool wait_until (unique_lock<mutex>& lck,                        const chrono::time_point<Clock,Duration>& abs_time,                        Predicate pred);
等待直到通知或指定时间点
当前线程的执行(该线程应已锁定 lck互斥量)被阻塞,直到通知或直到 abs_time,以先发生者为准。

在线程阻塞时,该函数会自动调用 lck.unlock(),允许其他已锁定的线程继续执行。

一旦被通知或一旦到达 abs_time,函数将解除阻塞并调用 lck.lock(),使 lck 保持在调用函数时的状态。然后函数返回(请注意,此最后的互斥量锁定可能会在返回前再次阻塞该线程)。

通常,函数通过另一个线程调用成员函数 notify_onenotify_all 来唤醒。但某些实现可能会产生虚假唤醒,而无需调用这些函数。因此,此函数的使用者应确保其恢复条件已满足。

如果指定了 pred (2),则仅当 pred 返回 false 时,该函数才会阻塞,并且只有在 pred 变为 true 时通知才能解除线程阻塞(这对于防止虚假唤醒尤其有用)。其行为如同实现为:
1
2
3
4
while (!pred())
  if ( wait_until(lck,abs_time) == cv_status::timeout)
    return pred();
return true;

参数

lck
一个 unique_lock 对象,其互斥量对象当前被该线程锁定。
所有对此对象的wait成员函数的并发调用都必须使用相同的底层互斥量对象(通过 lck.mutex() 返回)。
abs_time
一个时间点,线程将在该时间点停止阻塞,允许函数返回。
time_point 是表示特定绝对时间的对象。
pred
一个可调用对象或函数,它不接受任何参数,并返回一个可以被评估为 bool 的值。
此函数会反复调用 pred,直到其求值为 true

返回值

无条件版本 (1) 如果函数由于 abs_time 已到而返回,则返回 cv_status::timeout;否则返回 cv_status::no_timeout
谓词版本 (2) 返回 pred(),而不管超时是否被触发(尽管它只有在被触发时才能为 false)。

数据竞争

该函数执行三个原子操作:
  • lck 的初始解锁和同时进入等待状态。
  • 解除等待状态。
  • 在返回前锁定 lck
对对象的原子操作按照一个单一的总顺序进行排序,此函数中的三个原子操作以与上述相同的相对顺序发生。

异常安全

如果任何参数的值对此函数无效(例如,如果 lck互斥锁对象未被调用线程锁定),则会导致未定义行为

否则,如果抛出异常,则 condition_variable 对象和参数都处于有效状态(基本保证)。

在失败时可能抛出 system_error(将任何错误条件从相应的 lockunlock 调用中传递)。

谓词版本 (2) 也可能抛出由 pred 抛出的任何异常。

发生异常时,在退出函数作用域之前,会尝试恢复 lck 的状态(通过调用 lck.lock())。
如果与 abs_time 相关的操作抛出异常,则此函数可能抛出异常(请注意,在 <chrono> 中提供的标准 时钟持续时间 类型上的操作永远不会抛出)。

谓词版本 (2) 也可能抛出由 pred 抛出的异常。

如果函数在某个时刻未能恢复锁定并返回(例如,如果尝试锁定或解锁时抛出异常),则会调用 std::terminate

另见