首页 > 解决方案 > sleep_until 过去的一个时间点

问题描述

我有一个我认为很简单的模式 - 我想在未来 5 秒内创建一个时间点,运行一个可能需要一段时间的任务,然后睡到那个时间点(如果那个时间已经到了,可能根本不睡觉.) 但是,无论何时尝试使用std::this_thread::sleep_until过去的时间点,我的应用程序都会永远挂起。这是一个 MCVE:

#include <chrono>
#include <thread>

int main(){
  std::this_thread::sleep_until(std::chrono::steady_clock::now() - std::chrono::seconds(1));
}

使用 g++ (GCC) 4.8.5,这永远不会返回。我也尝试过 system_clock 的结果相同。使用 strace 检查发生了什么,我得到的最后一件事是:

nanosleep({4294967295, 0},

所以我想它最终会回来,但我不想等那么久。

这是一个 g++ 错误吗?我无法想象这种行为是故意的。我发现问题在指定过去的时间点时行为是否明确?sleep_until()但似乎并没有就该标准是否实际规定应该发生的事情得出任何结论。我已经为我的问题实施了另一种解决方案;我只是好奇我看到的是 UB 还是 bug。

标签: c++multithreadingchrono

解决方案


看起来像一个错误:

30.2.4 时序规范[thread.req.timing]

4   名称以结尾的_­until函数采用指定时间点的参数。这些函数产生绝对超时。实现应使用时间点中指定的时钟来测量这些功能的时间。 给定一个时钟时间点参数 C t ,在超时期间不调整时钟时,从超时返回的时钟时间点应该是 C t +D i +D m 。 (...)

其中,D i被定义为“实施质量”延迟,而 D m被定义为“管理质量”延迟。

正如 Howard Hinnant 出色地强调的那样,实现应该努力使 D i和 D m最小化:

30.2.4 时序规范[thread.req.timing]

2   实现在从超时返回时必然会有一些延迟。中断响应、函数返回和调度中的任何开销都会导致“实现质量”延迟,表示为持续时间 D i理想情况下,此延迟为零。此外,任何对处理器和内存资源的争用都会导致“管理质量”延迟,表示为持续时间 D m延迟持续时间可能因超时而异,但在所有情况下,越短越好。

请注意,无论 C t的值是多少,这都必须是正确的,并且无限延迟绝对不是最小的。

作为一个小更新,从 4.9.3 版开始,此问题现已修复。这是有关错误跟踪器的信息。


推荐阅读