C++ Logo

std-discussion

Advanced search

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

From: Tiago Freire <tmiguelf_at_[hidden]>
Date: Thu, 11 Jun 2026 10:33:05 +0000
I keep repeating and I don't think you understand what we are saying.

In your OP example if you find that 'now1 < now2', the result of the atomic load being 0 is a valid outcome.

I believe you got lost in nuances of distinctions without a difference.

Discussing anything else is pointless regardless of whatever it is you hope to practically achieve with this question.

________________________________
From: Std-Discussion <std-discussion-bounces_at_[hidden]> on behalf of jim x via Std-Discussion <std-discussion_at_[hidden]>
Sent: Thursday, June 11, 2026 11:16:57 AM
To: Jennifier Burnett <jenni_at_jburnett.me.uk>
Cc: jim x <xmh970252187_at_[hidden]>; std-discussion_at_[hidden] <std-discussion_at_[hidden]>
Subject: Re: [std-discussion] Does the C++ abstract machine recognize a temporal order of execution?


so the question of whether one statement executes before another on a machine that doesn't exist and will never execute the code is vacuous. You need to provide a visible outcome that you are expecting to be possible or not possible on the hypothetical machine.

The structure and semantics inside the abstract machine are not necessarily preserved in the observable behavior, but they are an important part of reasoning about possible execution outcomes. For instance, the modification order of an atomic object is only the semantic inside the abstract machine, and it is not the observable behavior; It is because of its existence that we know what the legitimate possible executions in the abstract machine are for a multi-threaded program.

On Thu, Jun 11, 2026 at 4:03 PM Jennifier Burnett <jenni_at_[hidden]<mailto:jenni_at_[hidden]>> wrote:
I think in this case we're somewhat losing the forest for the trees. How exactly would you test if #1 occurred before #2? The abstract machine is, well, abstract. It doesn't exist and is meaningful only in the possible executions it can allow, so the question of whether one statement executes before another on a machine that doesn't exist and will never execute the code is vacuous. You need to provide a visible outcome that you are expecting to be possible or not possible on the hypothetical machine.


On 11 June 2026 08:46:43 BST, jim x <xmh970252187_at_[hidden]<mailto:xmh970252187_at_[hidden]>> wrote:
In the OP, I don't think `#1` must be visible to `#4` when `now1 < now2`. As I said above, the visibility is guaranteed by the happens-before that has a strict definition in the specification. To avoid over-focus on the inter-thread happens-before, I think the original question can be simplified as an example that only comprises a single thread.

````cpp

#include <atomic>
#include <chrono>

std::atomic<int> val = 0;
int main(){
  val.store(1,std::memory_order::relaxed); // #1
  auto c1 = std::chrono::steady_clock::now(); // #2
}

````

The control flow first executes `#1`, then `#2`, while the control flow executing `#2` samples a global time point. So, the question is: Is `#1` executed by the control flow at a point in time that is no later than the time point represented by `c1`? Note that we only talk about this question in the abstract machine.

On Thu, Jun 11, 2026 at 3:22 PM Jennifier Burnett <jenni_at_[hidden]<mailto:jenni_at_[hidden]>> wrote:
Happens-before is very relevant because the question is about visibility between threads. The sequencing of statements in c++ is defined by the sequenced-before relation, which is implicitly upgraded to a happens-before relationship. The OP is asking if a write on one thread must become visible to a read on another thread if the latter observes a later time point from a call that is sequenced-before the read than the prior does from a call that is sequenced-after the write. Without a happens-before relationship between the read and the write that simply isn't possible because of trivial hardware optimisations like store buffering. Just because an execution on one thread happens temporally after an execution on another thread does not necessarily mean that the later execution has the same view of memory that the earlier one does.

My point is that unless you consider that observing a time point counts as a type of write there's no way of establishing the release part of the acquire-release relationship that's required for creating the happens-before.


On 11 June 2026 06:51:46 BST, jim x <xmh970252187_at_[hidden]<mailto:xmh970252187_at_[hidden]>> wrote:

What exactly would you be establishing a happens-before relationship with in the original example?

This is the misunderstanding of the OP. The OP doesn't talk about the happens-before relationship; instead, the intention can be simplified as talking about whether the control flow executing a previous expression occurs in no later time point than the time point it executes a later expression.

On Thu, Jun 11, 2026 at 1:37 PM Jennifier Burnett via Std-Discussion <std-discussion_at_[hidden]<mailto:std-discussion_at_[hidden]>> wrote:
An acquire barrier is meaningless in this context. An acquire barrier needs either a release operation or atomic operation preceded by a release barrier to have any semantics beyond relaxed. What exactly would you be establishing a happens-before relationship with in the original example? Assuming the call to now() is an implicit acquire barrier changes nothing about the semantics because there's no corresponding release for it to establish a happens-before relationship with. The first thread doesn't even have any operations other than the call to now() that the acquire barrier would apply to

On 11 June 2026 01:37:42 BST, Thiago Macieira via Std-Discussion <std-discussion_at_[hidden]<mailto:std-discussion_at_[hidden]>> wrote:
>On Wednesday, 10 June 2026 16:24:30 Pacific Daylight Time Simon Cooke wrote:
>> If you don't want that, you need acquire semantics, which will prevent the
>> write from down after the timestamp() call in #2
>
>This is the essence of the argument: reading from the monotonic clock should
>be an acquire barrier. The Standard does not say it is, but I think it should.
>
--
Std-Discussion mailing list
Std-Discussion_at_[hidden]<mailto:Std-Discussion_at_[hidden]>
https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion

Received on 2026-06-11 10:33:11