C++ how future::wait_until(time) handles multiple clocks?

TL;DR

std::future::wait_until(time) converts time to a standard clock, and thus implicitly assumes that all clocks run at the same pace.

More Details

I was writing unit tests for various retry scenarios, such as “try again after a minute”. With naïve approach, it would lead to very long running tests, which is a no-no. To avoid the waits, I abstracted access to the clock in the code, so I could “control time”. It worked great for the most part, but future::wait_until() refused to cooperate and gave me timeouts.

This made me wonder: how future::wait_until() handles multiple clocks in the first place?

C++ provides two standard clock types: system_clock, which is tied to an actual calendar time and steady_clock, which is guaranteed to never jump back and forth, but cannot be easily converted to calendar time. In practice it is usually the time since the machine boot. In theory, it should be possible to have user-defined clock types as well.

So, how future::wait_until() could handle a custom clock type? The answer is somewhat disappointing, but not surprising. Both GCC and MSVC implementations convert custom clock to a standard clock, and use that standard clock to wait. GCC uses vanilla std::chrono::system_clock, MSVC uses “xtime“, which is time in nanoseconds from some epoch. Coming to think of it, this is probably the only reasonable solution, since “clock” interface does not provide a wait facility.

This means that wait_until assumes that all clocks move at the same pace, which may not be true in the pretend world of unit tests.

The good news is that if the future is already satisfied, i.e. the result is already available, wait_until will ignore the time parameter, and will return immediately. So, it would work even if you pass it some weird time a few hundred years in the past.

So, the solution would be to either abstract the wait interface and avoid calling wait_until directly, or ensure that all futures are satisfied and wait_until is a no-op.

Posted in

Leave a Reply

Your email address will not be published. Required fields are marked *