Search code examples
c++timec++-chrono

Time-stamping using std::chrono - How to 'filter' data based on relative time?


I want to time-tag a stream of data I produce, for which I want to use std::chrono::steady_clock.

These time-stamps are stored with the data ( as array of uint64 values?), and I will later need to process these time-stamps again.

Now, I haven't been using the std::chrono library at all so far, so I do need a bit of help on the syntax and best practices with this library.

I can get & store values using:

uint64_t timestamp = std::chrono::steady_clock::now().time_since_epoch().count();

but how do I best:

  • On reading the data create a timepoint from the uint64 ?

  • Get the ticks-per-second (uint64) value for the steady_clock?

  • Find a "cut-off" timepoint (as uint64) that lies a certain time (in seconds) prior a given timepoint?

Code snippets for the above would be appreciated.

I want to combine the three above essentially to do the following: Having an array of (increasing) time-stamp values (as uint64), I want to truncate it such that all data 'older' than last-time-stamp minus X seconds is thrown away.


Solution

  • As it took me far too long to figure it out from various sources today, I'm going to post my solution here as self-answer. ( I would appreciate comments on it, in case something is not correct or could be done better.)

    Getting a clock's period in seconds and ticks-per-second value

        using namespace std::chrono;
        auto period = system_clock::period();
        double period_s = (double) period.num / period.den; 
        uint64 tps = period.den / period.num;
    

    Getting a clock's timepoint (now) as uint64 value for time-stamping a data stream

        using namespace std::chrono;
        system_clock::time_point tp_now = system_clock::now();
        uint64 nowAsTicks = tp_now.time_since_epoch().count();
    

    Getting a clock's timepoint given a stored uint64 value

        using namespace std::chrono;
        uint64 givenTicks = 12345;  // Whatever the value was
        system_clock::time_point tp_recreated = system_clock::time_point{} + system_clock::duration(givenTicks);
        uint64 recreatedTicks = tp_now.time_since_epoch().count();
        Assert( givenTicks == recreatedTicks );  // has to be true now
    

    The last ( uint64 to timepoint ) was troubling me the most. The key-insights needed were:

    • (On Win10) The system_clock uses a time-resolution of 100 nanoseconds. Therefore one can not directly add std::chrono::nanoseconds to its native time points. (std::chrono:system_clock_time_point)

    • However, because the ticks are 100's of nanoseconds, one can also not use the next higher duration unit (microseconds) as it cannot be represent as an integer value.

    • One could use use an explicit cast to microseconds, but that would loose the 0.1us resolution of the the tick.

    • The proper way is to use the system_clock's own duration and directly initialize it with the stored tick value.

    In my search I found the following resources most helpful: