[英]Persisting std::chrono time_point instances
持久化std :: chrono time_point实例然后将它们读回另一个相同类型的实例的正确方法是什么?
typedef std::chrono::time_point<std::chrono::high_resolution_clock> time_point_t;
time_point_t tp = std::chrono::high_resolution_clock::now();
serializer.write(tp);
.
.
.
time_point_t another_tp;
serializer.read(another_tp);
对write / read的调用,假设time_point_t类型的实例可以某种方式转换为字节表示,然后可以将其写入磁盘或套接字等或从磁盘或套接字读取。
Alf建议的可能解决方案如下:
std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();
//Generate POD to write to disk
unsigned long long ns0 = t0.time_since_epoch().count();
//Read POD from disk and attempt to instantiate time_point
std::chrono::high_resolution_clock::duration d(ns0)
std::chrono::high_resolution_clock::time_point t1(d);
unsigned long long ns1 = t1.time_since_epoch().count();
if ((t0 != t1) || (ns0 != ns1))
{
std::cout << "Error time points don't match!\n";
}
注意:上面的代码有一个错误,因为最终实例化的时间点与原始时间点不匹配。
在旧样式time_t的情况下,人们通常只是根据sizeof将整个实体写入磁盘,然后以相同的方式读取它 - 简而言之,新的std :: chrono类型的等价物是什么?
从磁盘或套接字读取意味着您可能正在读取未执行写入的应用程序实例。 在这种情况下,单独序列化持续时间是不够的。
time_point
是自未指定的纪元以来的duration
量。 这个时代可能是任何事物。 在我的计算机上, std::chrono::high_resolution_clock
的时代就是计算机启动时的时代。 即此时钟报告自引导以来的纳秒数。
如果一个应用程序写入time_since_epoch()。count(),计算机将重新启动,然后另一个(甚至是同一个)应用程序将其读回,读入值没有任何意义,除非您碰巧知道数量靴子之间的时间。
为了可靠地序列化time_point
,必须安排作者和读者就某个时期达成一致,然后确保写入和读取的time_point
与该时期有关。 例如,可以安排使用POSIX时代:1970年的新世界。
事实证明,我所知道的每个std::chrono::system_clock
实现都使用Unix时间 ,这是从1970年新年开始测量的UTC的近似值。但是我知道std::chrono::high_resolution_clock
没有共同的时代。
只有当你能够以某种方式确保读者和作者时钟在一个共同的时代上达成一致时,你才能将time_point序列化为持续时间。
time_point
构造函数占用一段duration
,您可以从成员time_since_epoch
获取duration
。 因此,问题减少了序列化duration
值。 和duration
有一个构造函数,它带有许多刻度,以及一个产生刻度数的成员函数count
。
所有这些只是通过谷歌搜索std::chrono::time_point
并查看cppreference文档谷歌让我std::chrono::time_point
。
阅读文档通常是个好主意。
附录 :一个例子。
#include <chrono>
#include <iostream>
#include <typeinfo>
using namespace std;
auto main() -> int
{
using Clock = chrono::high_resolution_clock;
using Time_point = Clock::time_point;
using Duration = Clock::duration;
Time_point const t0 = Clock::now();
//Generate POD to write to disk
Duration::rep const ns0 = t0.time_since_epoch().count();
//Read POD from disk and attempt to instantiate time_point
Duration const d(ns0);
Time_point const t1(d);
cout << "Basic number type is " << typeid( ns0 ).name() << "." << endl;
if( t0 != t1 )
{
cout << "Error time points don't match!" << endl;
}
else
{
cout << "Reconstituted time is OK." << endl;
}
}
使用Visual C ++ 12.0,报告的基本类型是__int64
,即long long
,而在Windows中使用g ++ 4.8.2时,报告的类型是x
,这可能意味着相同。
对于两个编译器,重构时间与原始时间相同。
附录 :正如Dina在评论中指出的那样,从C ++ 14开始,C ++标准没有指定时代,因此为了使这个工作跨越机器或使用不同的时钟,有必要添加额外的步骤来规范化时代。序列化数据,例如最自然地为Posix时间 ,即自1970年1月1日星期四00:00:00协调世界时(UTC)以来的时间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.