In refactoring some older Qt code that directly used clock_gettime() to use
std::chrono::steady_clock, I stumbled upon a limitation: I need to pass clock
time points to certain low-level functions. The one in particular I was
looking at is pthread_cond_timedwait(), whose timestamp must match the POSIX
clock set with pthread_condattr_setclock(). I wrote the code assuming that in
all systems std::chrono::steady_clock was the same as CLOCK_MONOTONIC, but
this isn't true in either Darwin systems (libc++ uses CLOCK_MONOTONIC_RAW) or
QNX (no clue what happens there).
Therefore, I'd like to propose that steady_clock add an extra method that
returns the clock ID. It could be as simple as:
[[pure]] static int clock_base();
1) what should this number be?
Ideally for me, it would be the POSIX clockid_t, so I could directly pass it
to pthread_condattr_setclock() or other POSIX RT functions. But we can't rely
on POSIX RT being supported in the operating system in question (read:
Windows, macOS < 10.12), therefore this function would have to be standardised
as "returns an implementation-specified value".
It could be called native_handle() in that case, and be optional / entirely impl-defined. But ...
A more standardisable alternative is to return the same clock constants that
are used by C11's timespec_get(). C11 introduced TIME_UTC and C23 is
introducing the (optional) TIME_MONOTONIC, with a future direction that it may
become mandatory. C11 also says that implementations may provide more clocks.
This would require updating our <ctime> reference up to C23, which is probably
reasonable. This solution would permit standard C and C++ code to have
interoperable time points.
However, the vendors of the C libraries and the C++ ones are seldom the same
and they have different release cycles. Right now, I don't know of any C
library that offers TIME_MONOTONIC. Requiring such an update before deploying
C++26 may not be possible in all systems. Moreover, many codebases would still
need to map from standard C TIME_ constants to POSIX CLOCK_ ones somehow,
unless POSIX provides such a function. Unfortunately, POSIX can't mandate that
they be the same value because CLOCK_REALTIME is often 0, but C11 required
TIME_UTC to be a positive value. POSIX should mandate that the formula
c_clock - TIME_UTC == posix_clock_id - CLOCK_REALTIME
hold true for all clocks.
That seems useful, but POSIX.1-202x is based on C17, so we won't get a new POSIX based on
C2x for several years.
If C library implementations commit to this formula, it becomes possible for
C++ standard libraries to anticipate the value that TIME_MONOTONIC will have,
even before it exists.
This should be raised with libc implementers ASAP, and with POSIX so it's on the radar once work on POSIX.1-202x is finished. I'll talk to some glibc people and if you want I can start a cross-vendor discussion.
Even if POSIX and libc vendors make that guarantee, is it really meaningful to convert arbitrary POSIX clock IDs from clockid_t to C time bases?
If I get an int which is not equal to TIME_UTC or TIME_MONOTONIC, can I use that value with timespec_get? If not, why are we munging POSIX clockid_t values into an int with a possibly different value? It seems like just returning a native_handle_type with an impl-defined meaning would be better. That would allow POSIX-based libraries to return a clockid_t (and document it as such) and other impls to return a C time base as an int, or just document that it never returns anything meaningful.
Unless we really want to encourage people to use C's timespec_get in code that is also using <chrono>, I don't see the point in aligning with timespec_get instead of aligning with POSIX. Your actual use case requires a clockid_t, wouldn't it be better to get that, without having to perform some conversion from int to clockid_t based on a convention we hope will get into a future POSIX standard?
2) should this be present in other std::chrono clocks?
Yes, I think so. With the C time.h clock bases, the standard clocks can return
0 to indicate that there is no match.
That is a benefit of using the C time base values, as POSIX doesn't seem to have an invalid clockid_t value or any restrictions on CLOCK_xxx constants (e.g. requiring that all valid clock IDs are non-negative).
And for a portable std::lib like libstdc++ it would be difficult to document what value would be returned to indicate no match (we can't know which clockid_t values are invalid on every OS we support).