vendredi 1 septembre 2017

Casting time_points between std::chrono clocks

The title line of this post is really only one half (the simpler half) of my question. So, I'll step back a moment to talk about what I'm trying to do.

It's pretty easy to measure elapsed time with std::chrono. However, I haven't seen any "Timer" implementations thus far that would do the equivalent of laps on a stopwatch. That is to say, you call Timer.start() when you want to start tracking intervals, and call Timer.tick() every time you want to record an interval. Then, after the fast stuff is over, you could look back on the list of time intervals recorded; maybe account for averages and 1% highs or something.

Also, because I use it a lot, I'd want to arbitrarily ask the timer how many microseconds have elapsed since midnight.

The first task for a constructor for this imaginary class would be to set midnight internally. Initially, I was doing this via the technique from this wonderful answer. As I went to implement my notion of a Timer class, though, I realized I wanted to use either high_resolution_clock or steady_clock (even though system_clock uses nanosecond intervals on my platform). The issue then arises: how to set a chrono::steady_clock::time_point to midnight?

Only system_clock has to_time_t and from_time_t, and in so far as I can tell, that's the only way to express "today at midnight" in a way that chrono understands. And for all my reading last night, I couldn't find a way to cast a system_clock::time_point to a steady_clock::time_point. My nearest attempt was:

typedef std::conditional<std::chrono::high_resolution_clock::is_steady,
                         std::chrono::high_resolution_clock,
                         std::chrono::steady_clock>::type TimerClock;

TimerClock::time_point midnight;

chrono::system_clock::time_point current_time = chrono::system_clock::now();

time_t raw_time = chrono::system_clock::to_time_t(current_time);

tm *tm_midnight = localtime(&raw_time);
tm_midnight->tm_hour = 0;
tm_midnight->tm_min  = 0;
tm_midnight->tm_sec  = 0;

midnight = chrono::system_clock::from_time_t(mktime(tm_midnight));

But obviously that won't fly. And in so far as I can tell, chrono::time_point_cast is designed to give you access to different resolutions from the same clock type.

This leaves me with two routes/questions:

  • Can I directly set the value of a time_point from high_precision_clock or steady_clock to be "today at midnight"
  • Can I convert a system_clock::time_point to be used with a different chrono clock?

And, of course, I'd be happy to be pointed to a better method of dealing with this all together, if it still lines up with my overall goals above.

Thanks in advance. =)

Aucun commentaire:

Enregistrer un commentaire