24

在 C++11 中,*_until只有在使用稳定时钟(即仅以不变的速率向前移动的时钟)时,超时函数才会“按预期”运行。因为system_clock不是一个稳定的时钟,这意味着这样的代码可能会表现得非常令人惊讶:

using namespace std::chrono;
std::this_thread::sleep_until(system_clock::now() + seconds(10));

这将导致当前线程休眠 10 秒,除非在休眠期间调整系统时钟,例如夏令时。如果在睡眠期间将时钟调回一小时,则当前线程将睡眠一小时十秒。

据我所知,*_untilC++11 中的每个超时函数都有一个相应的*_for函数,它需要一个持续时间而不是一个时间点。例如,上面的代码可以改写如下:

using namespace std::chrono;
std::this_thread::sleep_for(seconds(10));

这些*_for函数不必担心在函数执行时会调整时钟,因为它们只是说明等待多长时间,而不是等待结束时应该是什么时间。

这个问题影响的不仅仅是 sleep 函数,对于基于超时的 future 等待和 try_lock 函数也是如此。

*_until我可以设想使用具有不稳定时钟的函数的唯一情况是当您想要考虑时钟调整时,例如,您想睡到下周三凌晨 3:30,即使有变化从现在到那时的夏令时。在其他情况下,*_until函数比函数更有意义*_for吗?如果不是,是否可以肯定地说,一般来说,*_for超时函数应该优先于*_until函数?

4

3 回答 3

9

xxx_until电话是在您有截止日期时进行的。典型的用例是您对包含多个等待的一段代码有严格的时间限制,或者等待之前每个步骤所消耗的时间是不可预测的。

例如

void foo() {
  std::chrono::steady_clock::time_point const timeout=
    std::chrono::steady_clock::now()+std::chrono::milliseconds(30);

  do_something_which_takes_some_time();

  if(some_future.wait_until(timeout)==std::future_status::ready)
    do_something_with(some_future.get());
}

这只会处理从some_future开始后 30 毫秒内准备好的值,包括do_something_which_takes_some_time().

如本例所示, xxx函数的大多数用例_until将使用稳定的时钟,以实现可预测的超时。

我可以想象将xxx_until函数与非稳定时钟(例如std::chrono::system_clock)一起使用的唯一情况是超时是用户可见的,并且取决于所选时钟的值。闹钟或提醒程序是一个例子,“午夜”运行的备份程序是另一个例子。

于 2012-06-26T08:39:06.527 回答
4

该功能的一个用例sleep_until是,如果您想睡到特定时间,而不是特定持续时间。

例如,如果您有一个只应在每天下午 3 点激活的线程,您要么必须计算与 一起使用的持续时间(包括处理夏令时和闰年)sleep_for,或者您可以使用sleep_until.

于 2012-06-26T05:10:12.313 回答
3

for 的一个很好的用途sleep_until是稳定时间循环(如游戏循环)。如果您不确定处理一个周期需要多长时间,但它通常必须具有某个最小长度,您可以增加要休眠的 time_point 直到周期周期。例如:

// requires C++14
#include <iostream>
#include <thread>
#include <chrono>

using namespace std;
using namespace std::chrono;
using namespace std::literals;

int main()
{
  auto start_time = steady_clock::now();

  for (auto i = start_time; i <= start_time + 1s; i += 50ms) {
    this_thread::sleep_until(i);
    cout << "processing cycle..." << endl;
  }

  return 0;
}

但是,当一个周期花费的时间比增量时间长时,您可能必须跟踪滞后。

这个想法是,如果你天真sleep_for,你将在你的周期加上运行循环代码所需的时间。

于 2014-05-24T10:43:52.000 回答