简体   繁体   English

std :: condition_variable :: wait_for和std :: condition_variable :: wait_until有什么区别?

[英]What is the difference between std::condition_variable::wait_for and std::condition_variable::wait_until?

The reference I'm using explains the two in the following way: 我正在使用参考文献以下列方式解释了这两个:

  • wait_for "blocks the current thread until the condition variable is woken up or after the specified timeout duration" wait_for “阻塞当前线程,直到条件变量被唤醒或在指定的超时持续时间之后”

  • wait_until "blocks the current thread until the condition variable is woken up or until specified time point has been reached" wait_until “阻塞当前线程,直到条件变量被唤醒或达到指定的时间点”

What is the difference? 有什么区别? Will wait_until spin so that the thread can continue exactly (more or less) when it is signaled, whereas wait_for just adds the thread back into scheduling at that point? wait_until旋转,以便线程可以在发出信号时完全(或多或少)继续,而wait_for只是将线程添加回调度点?

The difference is in how the wait duration is represented: wait_for takes a relative time ("wait for up to 10 seconds"), whereas wait_until takes an absolute time ("wait until 12:00 on October 30, 2012"). 区别在于如何表示等待持续时间: wait_for需要相对时间(“等待最多10秒”),而wait_until需要一个绝对时间(“等到2012年10月30日12:00”)。

Compare the declarations of the time parameters: 比较时间参数的声明:

// wait_for:
const std::chrono::duration<Rep, Period>& rel_time

// wait_until:
const std::chrono::time_point<Clock, Duration>& abs_time

Your question and other answers have all repeated the difference; 你的问题和其他答案都重复了差异; that wait_for waits for a specified amount of time and wait_until waits until a specified point in time, but the implications are not spelled out. wait_for等待一段指定的时间, wait_until等到指定的时间点,但没有说明含义。

A time_point has an associated clock, and that clock is what's used to determine if the appropriate time has come. time_point具有相关的时钟,该时钟用于确定是否有适当的时间。 That means that clock adjustments are taken into account by the wait_until function. 这意味着wait_until函数会考虑时钟调整。 wait_until(..., system_clock::now() + std::chrono::seconds(10)) could end up waiting an hour and 10 seconds if the clock happens to be adjusted back by an hour before the wait is up. wait_until(..., system_clock::now() + std::chrono::seconds(10))如果时钟恰好在等待结束前一小时调整回来,可能会等待一小时10秒。

A duration does not have any associated clock and therefore wait_for chooses its own clock. 持续时间没有任何相关的时钟,因此wait_for选择自己的时钟。 The standard specifies that it uses std::steady_clock, which cannot be adjusted and advances at a steady rate relative to real time. 该标准规定它使用std :: steady_clock,它无法调整并以相对于实时的稳定速率前进。 This means that wait_for will wait for the specified time regardless of any adjustments made to any clocks. 这意味着无论对任何时钟进行任何调整, wait_for都将等待指定的时间。 wait_for(..., std::chrono::seconds(10)) is guaranteed to wait 10 seconds (+ some time for the implementation to work and for scheduling issues). wait_for(..., std::chrono::seconds(10))保证等待10秒(+实现工作和调度问题的时间)。

There is no difference with regard to spinning vs. sleeping the thread; 关于旋转与睡眠线程没有区别; as wait_for is specified to behave as if it called wait_until with steady_clock::now() + duration . 指定wait_for行为就像使用steady_clock::now() + duration调用wait_until steady_clock::now() + duration


Here's the part of the standard where this is spelled out: 这是标准的一部分,其中详细说明:

[thread.req.timing] 30.2.4/2-4 [thread.req.timing] 30.2.4 / 2-4

2 Implementations necessarily have some delay in returning from a timeout. 2实现从超时返回必然会有一些延迟。 Any overhead in interrupt response, function return, and scheduling induces a “quality of implementation” delay, expressed as duration D i . 中断响应,函数返回和调度中的任何开销都会引起“实现质量”延迟,表示为持续时间D i Ideally, this delay would be zero. 理想情况下,此延迟将为零。 Further, any contention for processor and memory resources induces a “quality of management” delay, expressed as duration D m . 此外,对处理器和存储器资源的任何争用都会引起“管理质量”延迟,表示为持续时间D m The delay durations may vary from timeout to timeout, but in all cases shorter is better. 延迟持续时间可能因超时而异,但在所有情况下,更短的更好。

3 The member functions whose names end in _for take an argument that specifies a duration. 3名称以_for结尾的成员函数采用指定持续时间的参数。 These functions produce relative timeouts. 这些函数产生相对超时。 Implementations should use a steady clock to measure time for these functions. 实现应该使用稳定的时钟来测量这些功能的时间。 Given a duration argument D t , the real-time duration of the timeout is D t + D i + D m . 给定持续时间参数D t ,超时的实时持续时间是D t + D i + D m

4 The member functions whose names end in _until take an argument that specifies a time point. 4名称以_until结尾的成员函数采用指定时间点的参数。 These functions produce absolute timeouts. 这些函数产生绝对超时。 Implementations should use the clock specified in the time point to measure time for these functions. 实现应使用时间点中指定的时钟来测量这些功能的时间。 Given a clock time point argument C t , the clock time point of the return from timeout should be C t + D i + D m when the clock is not adjusted during the timeout. 给定时钟时间点参数C t ,当超时期间未调整时钟时,从超时返回的时钟时间点应为C t + D i + D m If the clock is adjusted to the time C a during the timeout, the behavior should be as follows: 如果在超时期间将时钟调整到时间C a ,则行为应如下所示:
— if C a > C t , the waiting function should wake as soon as possible, ie C a + D i + D m , since the timeout is already satisfied. - 如果C a > C t ,则等待功能应尽快唤醒,即C a + D i + D m ,因为已经满足超时。 [ Note: This specification may result in the total duration of the wait decreasing when measured against a steady clock. [ 注意:当针对稳定时钟测量时,此规范可能导致等待的总持续时间减少。 —end note ] - 尾注 ]

— if C a <= C t , the waiting function should not time out until Clock::now() returns a time C n >= C t , ie waking at C t + D i + D m . - 如果C a <= C t ,则等待函数不应超时,直到Clock::now()返回时间C n > = C t ,即在C t + D i + D m处唤醒。 [ Note: When the clock is adjusted backwards, this specification may result in the total duration of the wait increasing when measured against a steady clock. [ 注意:当向后调整时钟时,此规范可能会导致等待的总持续时间在稳定时钟下测量时增加。 When the clock is adjusted forwards, this specification may result in the total duration of the wait decreasing when measured against a steady clock. 当向前调整时钟时,该规范可能导致在对稳定时钟进行测量时等待的总持续时间减少。 —end note ] - 尾注 ]

An implementation shall return from such a timeout at any point from the time specified above to the time it would return from a steady-clock relative timeout on the difference between C t and the time point of the call to the _until function. 实现应在从上面指定的时间到从C t和调用_until函数的时间点之间的差值的稳定时钟相对超时返回的任何时刻从这样的超时返回。 [ Note: Implementations should decrease the duration of the wait when the clock is adjusted forwards. [ 注意:当时钟向前调整时,实现应该减少等待的持续时间。 —end note ] - 尾注 ]

  • wait_for will wait for a certain amount of time. wait_for将等待一段时间。 It will for example wait for two seconds. 例如,它将等待两秒钟。
  • wait_until will wait until some time is reached. wait_until将等到一段时间后才会到达。 It will for example wait until 23rd of July 2013 11:22:34 pm is reached on the clock. 例如,它将等到2013年7月23日晚上11:22:34到达时钟。

Here is one important difference in their usage as explained in Anthony Williams's book : 正如Anthony Williams的书中所解释的,这是他们使用中的一个重要区别:

Consider this example where a condition variable is waited with a timeout: 考虑这个示例,其中条件变量等待超时:

std::condition_variable cv;
bool done;
std::mutex m;

bool wait_loop()
{
    auto const timeout= std::chrono::steady_clock::now()+
    std::chrono::milliseconds(500);
    std::unique_lock<std::mutex> lk(m);
    while(!done)
    {
       if(cv.wait_until(lk,timeout)==std::cv_status::timeout)
          break;
    }
    return done;
}

This is the recommended way to wait for condition variables with a time limit, if you're not passing a predicate to the wait. 如果您没有将谓词传递给等待,那么这是等待具有时间限制的条件变量的推荐方法。 This way, the overall length of the loop is bounded . 这样,循环的总长度是有界的 As you saw in section 4.1.1, you need to loop when using condition variables if you don't pass in the predicate, in order to handle spurious wakeups. 正如您在第4.1.1节中看到的那样,如果您没有传入谓词,则需要在使用条件变量时循环,以便处理虚假唤醒。 If you use wait_for() in a loop, you might end up waiting almost the full length of time before a spurious wake, and the next time through the wait time starts again. 如果你在循环中使用wait_for() ,你可能会在虚假唤醒之前等待几乎整个时间长度,并且下一次等待时间再次开始。 This may repeat any number of times, making the total wait time unbounded . 这可能会重复任何次数,使总等待时间无限制

IMO, this is one such scenario where wait_for can't replace wait_until so easily, because of its resetting nature. IMO,这是一个这样的场景,其中wait_for无法轻易替换wait_until ,因为它的重置性质。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM