If I have a time_point for an arbitrary clock (say high_resolution_clock::time_point), is there a way to convert it to a time_point fo
There's no way to do this precisely unless you know the precise duration difference between the two clock's epochs. And you don't know this for high_resolution_clock and system_clock unless is_same is true.
That being said, you can program up an approximately correct translation and it goes much like T.C. says in his comment. Indeed, libc++ plays this trick in its implementation of condition_variable::wait_for:
https://github.com/llvm-mirror/libcxx/blob/78d6a7767ed57b50122a161b91f59f19c9bd0d19/include/__mutex_base#L455
The calls to now of the different clocks are made as close together as possible, and one hopes that the thread isn't pre-empted between these two calls for too long. It's the best I know how to do, and the spec has wiggle room in it to allow for these types of shenanigans. E.g. something is allowed to wake up a little late, but not a little early.
In the case of libc++, the underlying OS only knows how to wait on system_clock::time_point, but the spec says you must wait on steady_clock (for good reasons). So you do what you can.
Here is a HelloWorld sketch of the idea:
#include
#include
std::chrono::system_clock::time_point
to_system(std::chrono::steady_clock::time_point tp)
{
using namespace std::chrono;
auto sys_now = system_clock::now();
auto sdy_now = steady_clock::now();
return time_point_cast(tp - sdy_now + sys_now);
}
std::chrono::steady_clock::time_point
to_steady(std::chrono::system_clock::time_point tp)
{
using namespace std::chrono;
auto sdy_now = steady_clock::now();
auto sys_now = system_clock::now();
return tp - sys_now + sdy_now;
}
int
main()
{
using namespace std::chrono;
auto now = system_clock::now();
std::cout << now.time_since_epoch().count() << '\n';
auto converted_now = to_system(to_steady(now));
std::cout << converted_now.time_since_epoch().count() << '\n';
}
For me, using Apple clang/libc++ at -O3 this output:
1454985476610067
1454985476610073
indicating the combined conversion had an error of 6 microseconds.
Update
I have arbitrarily reversed the order of the calls to now() in one of the conversions above such that one conversion calls them in one order, and the other calls them in the reverse order. This should have no impact on the accuracy of any one conversion. However when converting both ways as I do in this HelloWorld, there should be a statistical cancellation which helps to reduce the round-trip conversion error.