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: Thu, 11 Jun 2026 10:54:35 +0800
>
> Control flow can reach #2 without executing #1, because ordering is
> relaxed. The CPU is free to move the store instruction beyond timestamp()
> call (which will resolve to a single instruction on most architectures). If
> you don't want that, you need *acquire* semantics, which will prevent the
> write from down after the timestamp() call in #2. The only time anything
> gets synchronized here at all is that ending the thread will flush any
> pending loads/stores before it dies - so you can guarantee that after the
> thread has ended, both #1 and #2 have completed.


This is complete about how a real implementation, or a conforming
implementation, can do under the "as-if" rule. However, I only talk about
the semantics of the abstract machine; therefore, no reordering is involved.


You can't guarantee that all of t2 won't execute before all of t1.
>

This is also a possible execution; however, regardless of what order
they're executed, under the assumption `now1 < now2`, this means the
control flow of `t1` executing `#2` samples a time point that is less than
the time point value sampled by the control flow of `t2` executing `#3`. If
you change `#1` and `#4` to `now()`, the value returned by `#1` must be
less than that of `#4`.

On Thu, Jun 11, 2026 at 7:25 AM Simon Cooke via Std-Discussion <
std-discussion_at_[hidden]> wrote:

> So I'm a little rusty. Apologies if this is completely wrong.
>
> First, creating the threads in both cases means that operations in t1 and
> operations in t2 are *not* ordered with respect to one another. You have
> zero guarantees over which thread will start to execute first, in which
> order, or if they'll even have to co-operatively pre-empt one another on a
> single core, or operate across multiple cores. There's always a chance that
> something will happen and cause them to swap order, or run in unexpected
> ordering, unless you explicitly ad synchronization points.
>
> You state:
>
>> 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.
>
>
> Control flow can reach #2 without executing #1, because ordering is
> relaxed. The CPU is free to move the store instruction beyond timestamp()
> call (which will resolve to a single instruction on most architectures). If
> you don't want that, you need *acquire* semantics, which will prevent the
> write from down after the timestamp() call in #2. The only time anything
> gets synchronized here at all is that ending the thread will flush any
> pending loads/stores before it dies - so you can guarantee that after the
> thread has ended, both #1 and #2 have completed.
>
> 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?
>
>
> You can't guarantee that all of t2 won't execute before all of t1. And
> even if you could guarantee that they would execute in parallel on two
> cores, #4 can occur at any point within t2, as again, it has relaxed
> ordering. To get the behavior you want, you need to specify that #4 has
> *release* semantics.
>
> It'd be different if, say, the code was this:
>
> auto t1 = std::thread([&]() {
>> int temp = timestamp();
>>
> val.store(temp,relaxed);
>
>> });
>>
>
> ... for t1, as val.store() relies on the value read from int temp(), so
> the loads/stores involved can't float around and be exercised in sequence.
>
> Does that help at all?
>
> On Wed, Jun 10, 2026 at 3:14 PM Thiago Macieira via Std-Discussion <
> std-discussion_at_[hidden]> wrote:
>
>> On Wednesday, 10 June 2026 10:49:17 Pacific Daylight Time Tiago Freire
>> wrote:
>> > > Inconsistent monotonic clocks are a bug in the platform
>> implementation and
>> > > a violation of the Standard that should be fixed by said
>> implementation.
>> > Is it? Regardless, I don't think this is the point being discussed here.
>>
>> Yes and I agree not what was being discussed.
>>
>> An inconsistent monotonic clock could show up as a "clock went backwards"
>> if
>> the thread got de-scheduled from one computing device and scheduled in
>> another. The window of time this could happen is very small, and context-
>> switching is usually pretty costly, but never say never.
>>
>> The amount of silicon area and resources on Intel processors dedicated to
>> ensuring that the time stamp counters are kept monotonic and clock-
>> independent, and yet quick to access, is massive. I don't know about
>> other
>> architectures, but it has to be similar.
>>
>> However, while the inconsistent clock itself was not the point, the
>> *consistency* of reading a clock was.
>>
>> > I think the point being discussed here is if you have a thread X where
>> you
>> > write the code to do A then B, and you have a thread Y where you write
>> code
>> > to do C then D, if you can deduce that C happened after B is it
>> guaranteed
>> > that D happened after A?
>> >
>> > And the answer to that question is No.
>>
>> That depends on the sequence of happens-before relationships. We have a
>> very
>> large section of the Standard dedicated to explaining this.
>>
>> What is missing is whether there is any happens-before of any kind
>> relating to
>> the steady_clock. I think there should be.
>>
>> > For the particular case of reading a clock, I assume that on most
>> > implementations a barrier would be involved somewhere, and as you have
>> > seemed to correctly point out in a separate email.
>>
>> I've pointed out one example. And while I think it is necessary for there
>> to
>> be a happens-before via release/acquire, I am not so certain all
>> implementations do it properly.
>>
>> > But an implementation where reading a clock would still allow for other
>> > instructions around it to be reordered before or after the read, looks
>> to
>> > me too also be a valid implementation.
>>
>> Reordering, yes.
>>
>> The question is back to the point of the OP: is a happens-before
>> relationship
>> required? The Standard doesn't say anything.
>>
>> I think it should. Therefore, reordering is permitted, so long as the
>> observed
>> external behaviour is that of the happens-before sequence.
>>
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Principal Engineer - Intel Data Center - Platform & Sys. Eng.
>> --
>> Std-Discussion mailing list
>> Std-Discussion_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>

Received on 2026-06-11 02:54:50