C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Obtaining the low-level clock used by std::chrono::steady_clock

From: Thiago Macieira <thiago_at_[hidden]>
Date: Thu, 20 Apr 2023 07:21:41 -0700
On Thursday, 20 April 2023 03:26:40 PDT Jonathan Wakely wrote:
> > 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.

timespec_get is C11, meaning it and TIME_UTC are part of that POSIX.1 you're
referring to. It has also said in "Future Library directions" that more macros
beginning with TIME_ may be added, which is happening with C23. The fact that
C23 is adding TIME_MONOTONIC should inform POSIX of where this is going.

Besides, POSIX can extend the C language and they can define their own TIME_
bases.

> > 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.

Let's do that. I have glibc contacts, but not in other libcs and not in POSIX.
I'd appreciate the help.

> 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?

I don't see why not. I don't see why any clock_gettime() and timespec_get()
would want to support an unequal set of clocks...

Right now, on all Unix systems, timespec_get() is a wrapper around
clock_gettime(), with a check that the base is TIME_UTC. The MUSL
implementation is simply:

int timespec_get(struct timespec * ts, int base)
{
        if (base != TIME_UTC) return 0;
        int ret = __clock_gettime(CLOCK_REALTIME, ts);
        return ret < 0 ? 0 : base;
}

> 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?

As I said, for me, the POSIX RT clockid_t would be better, because that's what
I really need. I only raised the C11 TIME_ time base as an option because
we've imported that into C++.

Of course, we can always have both too. If we name the clockid_t-returning
method native_handle() as you suggested, we leave the room open to returning
the C time base with a different method, should the need arise.

> 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).

Right. I had some preprocessor code in Qt (erased this week) that attempted to
determine if they were all positive or all negative, by checking if
CLOCK_REALTIME and CLOCK_MONOTONIC were both non-positive or both non-
negative, so we could define the opposite sign as CLOCK_INVALID. But our code
only ever needed those two, so it didn't matter if it also matched a valid
clock.

If we go for the POSIX clockid_t and native_handle(), how do you suppose
libstdc++ and libc++ would handle being required to offer a native_handle() for
tai_clock? On Linux, that's clearly CLOCK_TAI, but that doesn't exist on
FreeBSD.

-- 
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel DCAI Cloud Engineering

Received on 2023-04-20 14:21:43