【问题标题】:Timer wrap-around problems定时器环绕问题
【发布时间】:2018-01-02 19:00:28
【问题描述】:

下面的代码是否正确

添加事件:

pushEvent(std::chrono::steady_clock::now() + dt, event_obj);

在事件循环中:

//...
auto now=std::chrono::steady_clock::now();
if(event.expireTime<=now)
    {
    event.fire();
    }
//...

我有点担心环绕行为,因为我知道至少有两个错误 [1] 和 [2],这是由于时间计数器的环绕而引入的。我认为可能发生的事情:

【问题讨论】:

    标签: c++11 integer-overflow chrono


    【解决方案1】:

    您可以使用steady_clock::time_point::max().time_since_epoch() 检查steady_clock::time_point 的范围。这将返回一个chrono::duration,这是自steady_clock 纪元以来的最大时间量。时代本身是未指定的。然而这个:

    auto time_left = steady_clock::time_point::max() - steady_clock::now();
    

    为您提供直到max() 被击中的时间。 time_left 的确切单位可以通过以下方式检查:

    using D = decltype(time_left);
    std::cout << D::period::num << '/' << D::period::den << '\n';
    

    在每个平台上输出:

    1/1000000000
    

    这意味着单位是纳秒。所以你可以:

    std::cout << time_left.count() << "ns\n";
    

    如果你愿意使用我的free, header-only date/time library,它会为你进行内省,你可以这样做:

    using date::operator<<;
    std::cout << time_left << "\n";
    

    对我来说这个输出:

    9221890448824928278ns
    

    大约是 292 年。如果你的代码在我的平台上运行,它可能会在 292 年内完成。您的平台可能类似,这就是您可以测试的方式。

    【讨论】:

    • 所以答案是,no,不过没关系,因为在各大平台上持续时间都够长?
    • 不要相信我的话。使用上述工具形成您自己的(新获知的)结论。还有time_point::max() 和其他所有东西一样,都是编译时信息,所以你可以static_assert 就可以了。
    • 据我计算,其实是29.2年。
    • 2^63/(10^9 * 86400 * 365.2425) = 292.277...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 2015-11-13
    • 2011-09-10
    • 1970-01-01
    相关资源
    最近更新 更多