C++ Logo

std-discussion

Advanced search

Re: Does the C++ abstract machine recognize a temporal order of execution?

From: jim x <xmh970252187_at_[hidden]>
Date: Wed, 10 Jun 2026 21:45:41 +0800
As I said in this subject, we only talk about the question in the *abstract
machine.* So, how `std::chrono::steady_clock::now()` behaves is only
according to the relevant rules.

In general “temporal order of execution” is not a guaranteed thing, only
> “observable effects will be as-if in order in restricted circumstances” are
> guaranteed, but there are some functions/features to explicitly ensure that
> certain things happen in a particular order.


Again, "as-if" only applies to conforming implementations. We're talking
about the case in the C++ abstract machine. This is like we talked about
"sequence-before" in the abstract machine and concluded what the observable
behavior should be based on the original structure. In this process, we
don't need to consider reordering; that's the matter of implementations
under the "as-if" rule.

On Wed, Jun 10, 2026 at 7:40 PM Tiago Freire <tmiguelf_at_[hidden]> wrote:

> For your example, “it depends”, on how std::chrono::steady_clock::now() is
> implemented.
>
>
>
> In general “temporal order of execution” is not a guaranteed thing, only
> “observable effects will be as-if in order in restricted circumstances” are
> guaranteed, but there are some functions/features to explicitly ensure that
> certain things happen in a particular order.
>
>
>
> This has been a thing for a while now, and it’s not even just because of
> the language, but also because of out of order execution in modern cpu
> design.
>
>
>
> *From:* Std-Discussion <std-discussion-bounces_at_[hidden]> *On
> Behalf Of *jim x via Std-Discussion
> *Sent:* Wednesday, June 10, 2026 11:47
> *To:* jim x via Std-Discussion <std-discussion_at_[hidden]>
> *Cc:* jim x <xmh970252187_at_[hidden]>
> *Subject:* [std-discussion] Does the C++ abstract machine recognize a
> temporal order of execution?
>
>
>
> Consider this example:
>
> ````cpp
> #include <atomic>
> #include <chrono>
> #include <thread>
>
> uint64_t timestamp() {
> auto now = std::chrono::steady_clock::now().time_since_epoch();
> return
> std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
> }
>
> int main() {
> std::atomic<long int> val = 0;
> long int now1, now2;
> auto t1 = std::thread([&]() {
> val.store(1,relaxed); // #1
> now1 = timestamp(); // #2
> });
> auto t2 = std::thread([&]() {
> now2 = timestamp(); // #3
> val.load( relaxed ); // #4
> });
> t1.join();
> t2.join();
> }
>
> ````
>
> This question arises from whether we can determine if a specific execution
> outcome is caused by inter-thread latency within the abstract machine. A
> possible execution of the above example is that #4 reads 0 even when now1
> < now2.
>
>
>
> Both intro.execution p8 <https://eel.is/c++draft/intro.execution#8>
>
> > Given any two evaluations A and B, if A is sequenced before B (or,
> equivalently, B is sequenced after A), *then the execution of A shall
> precede the execution of B*.
>
>
>
> and [stmt.pre] p1
>
> > Except as indicated, statements are executed in sequence
> ([intro.execution]).
>
>
>
> state that the control flow executes expressions in sequential order
> within a single thread, provided one evaluation is sequenced before another.
>
>
>
> Furthermore, *[time.clock.steady] p1* states:
>
> > Objects of class steady_clock represent clocks for which values of
> time_point never decrease as physical time advances and for which values of
> time_point advance at a steady rate relative to real time. That is, the
> clock may not be adjusted.
>
>
>
> and *[time.clock.req] p2* states:
>
> > C1::now(): Returns a time_point object representing the current point in
> time.
>
>
>
> This implies that calling now() samples a global time point when the
> control flow executes it. Since the control flow cannot reach #2 without
> first executing #1, #1 must be executed by the control flow at a point in
> time no later than the time point returned by #2. The same logic applies
> to #3 and #4.
>
>
>
> Therefore, when now1 < now2, does it imply that #1 is executed by the
> control flow of t1 at a point in time strictly earlier than when #4 is
> executed by the control flow of t2, from the perspective of the abstract
> machine? (Note that this does not refer to a happens-before relationship,
> but rather a temporal comparison of the control flows executing these
> expressions.)
>
>
>
> As a minor clarification, this is not a question about physical
> implementations (which are governed by the "as-if" rule), but rather a
> conceptual question about the formal behavior defined by the C++ abstract
> machine.
>
>
>
> The deduction above is based entirely on existing rules within the
> standard, and there seems to be no explicit rule that contradicts this
> interpretation. Consequently, this appears to be a gray area in the
> specification. If this reasoning is indeed flawed, where exactly does the
> flaw lie? Furthermore, are there any specific rules in the standard that
> would directly negate this conclusion?
>

Received on 2026-06-10 13:45:57