[英]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.