【问题标题】:sleep_until a timepoint in the pastsleep_until 过去的一个时间点
【发布时间】:2018-08-08 20:36:35
【问题描述】:

我有一个我认为很简单的模式 - 我想在未来 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++ 错误吗?我无法想象这种行为是故意的。我发现了Is behaviour well-defined when sleep_until() specifies a time point in the past? 的问题,但似乎并没有就标准是否实际指定应该发生的事情得出任何结论。我已经为我的问题实施了另一种解决方案;我只是好奇我看到的是 UB 还是 bug。

【问题讨论】:

  • 这看起来像一个错误。在 4.9 或更高版本上它不会挂起。
  • 我的回答错了,所以我把它删了。标准中的措辞并没有真正指定,据我所知,当 time_point 过去时会发生什么。不过,它看起来仍然像一个错误。
  • 它确实指定了,但是,如果时钟调整到所述时间点之后,它应该尽快唤醒。这就是我在回答中(错误地)引用的内容。
  • @CássioRenan:我是在您删除答案之前对您的答案进行投票的人,我也是在&lt;chrono&gt;_until 函数上领导标准化过程的人。如果规范没有说这是一个错误,那么规范中也有一个错误。如果您对如何改进规范有任何建议,请here is how to go about that
  • @HowardHinnant 我知道 Stackoverflow 并不是真正的“谢谢”之类的地方,但我必须说我们在这里的小交流激发了我更多的学习,我终于可以阅读这部分标准并充分理解它,可以说我知道我在说什么,我以前不习惯这样做。所以,非常感谢! (顺便说一句,该错误已在 gcc 上修复:我已经更新了答案)。

标签: c++ multithreading chrono


【解决方案1】:

看起来像一个错误:

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

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

其中 Di 被定义为“实施质量”延迟,而 Dm 被定义为“管理质量”延迟。

As Howard Hinnant brilliantly emphasizes,实现应该努力最小化 Di 和 Dm

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

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

请注意,无论 Ct 的值是多少,这都必须为真,并且无限延迟绝对不是最小的。

作为一个小更新,this is now fixed,从版本 4.9.3 开始。 Here is the information on the bug tracker.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    • 2022-12-11
    • 1970-01-01
    • 1970-01-01
    • 2020-08-30
    • 1970-01-01
    相关资源
    最近更新 更多