在c ++ 11时钟之间转换

时间:2016-02-09 01:10:04

标签: c++ c++11 chrono

如果我有一个time_point用于任意时钟(比如high_resolution_clock::time_point),有没有办法将其转换为time_point另一个任意时钟(比如system_clock::time_point )?

我知道如果存在这种能力,就必须有限制,因为并非所有时钟都是稳定的,但有没有任何功能可以帮助规范中的这种转换?

1 个答案:

答案 0 :(得分:16)

除非你知道两个时钟的时代之间的精确持续时间差异,否则无法准确地做到这一点。除非high_resolution_clocksystem_clock,否则您不会对is_same<high_resolution_clock, system_clock>{}true了解这一点。

话虽这么说,你可以编写一个近似正确的翻译,它就像T.C.在他的评论中所说的那样。实际上,libc ++在condition_variable::wait_for

的实现中扮演了这个伎俩

https://github.com/llvm-mirror/libcxx/blob/master/include/__mutex_base#L385-L386

对不同时钟的now的调用尽可能紧密地联系在一起,并且希望线程不会在这两个 的调用之间被抢先一步长。它是我所知道的最好的方法,并且规范在其中有摆动空间以允许这些类型的恶作剧。例如。允许有些东西醒来有点晚,但不是很早。

对于libc ++,底层操作系统只知道如何等待system_clock::time_point,但规范说你必须等待steady_clock(有充分理由)。所以你尽你所能。

这是一个关于这个想法的HelloWorld草图:

#include <chrono>
#include <iostream>

std::chrono::system_clock::time_point
to_system(std::chrono::steady_clock::time_point tp)
{
    using namespace std::chrono;
    auto sys_now = system_clock::now();
    auto sdy_now = steady_clock::now();
    return time_point_cast<system_clock::duration>(tp - sdy_now + sys_now);
}

std::chrono::steady_clock::time_point
to_steady(std::chrono::system_clock::time_point tp)
{
    using namespace std::chrono;
    auto sdy_now = steady_clock::now();
    auto sys_now = system_clock::now();
    return tp - sys_now + sdy_now;
}

int
main()
{
    using namespace std::chrono;
    auto now = system_clock::now();
    std::cout << now.time_since_epoch().count() << '\n';
    auto converted_now = to_system(to_steady(now));
    std::cout << converted_now.time_since_epoch().count() << '\n';
}

对我来说,在-O3使用Apple clang / libc ++这个输出:

1454985476610067
1454985476610073

表示组合转换的误差为6微秒。

<强>更新

我已经在上述某个转换中随意颠倒了对now()的调用顺序,以便一次转换以一个顺序调用它们,另一个转换以相反的顺序调用它们。此应该对任何一个转换的准确性没有影响。但是,当我在此HelloWorld中转换两种方式时,应该有统计消除,这有助于减少往返转换错误。