为什么STD :: Chrono :: Time_point不够大,无法存储struct timespec



我正在尝试最近的std::chrono API,我发现在64位Linux体系结构和GCC编译器上time_pointduration类无法处理操作系统的最大时间范围最大分辨率(纳秒(。实际上,与timespectimeval相比,这些类的存储似乎是64位积分类型,它们在内部使用两个64位整数,一个用于秒,一个用于纳米秒:

#include <iostream>
#include <chrono>
#include <typeinfo>
#include <time.h>
using namespace std;
using namespace std::chrono;
int main()
{
    cout << sizeof(time_point<nanoseconds>) << endl;                       // 8
    cout << sizeof(time_point<nanoseconds>::duration) << endl;             // 8
    cout << sizeof(time_point<nanoseconds>::duration::rep) << endl;        // 8
    cout << typeid(time_point<nanoseconds>::duration::rep).name() << endl; // l
    cout << sizeof(struct timespec) << endl;                               // 16
    cout << sizeof(struct timeval) << endl;                                // 16
    return 0;
}

在64位Windows(MSVC2017(上,情况非常相似:存储类型也是64位整数。当处理稳定(又称单调(时钟时,这不是问题,但是存储限制使不同的API实现不适合存储更大的日期和更宽的时间跨度,从而为类似Y2K的错误创造了基础。问题被确认吗?是否有更好的实施或API改进的计划?

这是这样做的,以便您获得最大的灵活性以及紧凑的大小。如果您需要超细精度,则通常不需要非常大的范围。而且,如果您需要很大的范围,通常不需要很高的精度。

例如,如果您正在贩运纳秒,您是否经常考虑/- 292年?而且,如果您需要考虑一个比这更大的范围,那么微秒井会给您/- 292 千年年。

MACOS system_clock实际上返回微秒,而不是纳秒。从1970年起,时钟可以运行29.2千年。

Windows system_clock的精度为100 ns单元,因此/- 292千年。

如果数十万年还不够,请尝试毫秒。现在,您的范围为/- 292 百万年。

最后,如果您只有具有纳秒精度超过几百年,则<chrono>也允许您自定义存储空间:

using dnano = duration<double, nano>;

这使您可以将纳秒存储为double。如果您的平台支持128位积分类型,则可以使用它:

using big_nano = duration<__int128_t, nano>;

heck,如果您为timespec编写超载的操作员,甚至可以将使用用于存储(虽然我不建议它(。

您还可以实现比纳秒秒更好的精确度,但是您会牺牲范围。例如:

using picoseconds = duration<int64_t, pico>;

这仅有/- .292年(几个月(。因此,您 do 必须小心。尽管您有一个源时钟可以给您子纳秒精度。

,非常适合时间。

查看此视频以获取有关<chrono>的更多信息。

用于创建,操纵和存储日期的范围大于当前Gregorian日历的有效性,我创建了此开放式日期库,该库将使用日历服务扩展了<chrono>库。该图书馆将这一年存储在一个签名的16位整数中,因此/- 32K年。可以这样使用:

#include "date.h"
int
main()
{
    using namespace std::chrono;
    using namespace date;
    system_clock::time_point now = sys_days{may/30/2017} + 19h + 40min + 10s;
}

update

在下面的评论中,问如何将 duration<int32_t, nano>归一化为秒和纳秒(然后将秒添加到time_point(。

(。

首先,我会谨慎地将纳秒塞入32位。该范围只有/- 2秒。但这是我将这样的单位分开的方式:

    using ns = duration<int32_t, nano>;
    auto n = ns::max();
    auto s = duration_cast<seconds>(n);
    n -= s;

请注意,仅当n为正时,这才有效。要正确处理负n,最好的办法是:

    auto n = ns::max();
    auto s = floor<seconds>(n);
    n -= s;

std::floor使用C 17引入。如果您愿意的话,可以从这里或这里抓住它。

我是上面的减法操作的部分,因为我发现它更可读。但这也有效(如果n不是负面(:

    auto s = duration_cast<seconds>(n);
    n %= 1s;

1s在C 14中引入。在C 11中,您必须使用seconds{1}

有秒(s(后,您可以将其添加到time_point

std::chrono::nanosecondsstd::chrono::duration<some_t, std::nano>的类型别名,其中some_t是一个签名的INT,存储至少64位。这仍然允许纳秒精度至少有292年的范围。

值得注意的是,唯一具有标准特征的积分类型是int(| _fast | _least(64_t家族。

如果您的实现提供了一个,则可以自由选择更广泛的类型来表示您的时间。您可以免费提供一个命名空间,其中包含一堆typedef的命名空间,这些命名空间以 std::chrono的比率为单位,而较宽的类型为表示。

相关内容

  • 没有找到相关文章

最新更新