Date: Fri, 12 Jun 2026 06:28:07 +0000
> I talked about that, for two evaluations `A` and `B`, whether the control flow executes `A` at a point in time that is no later than when it executes `B` is a valid semantics in the abstract machine?
I have already answered this.
From: jim x <xmh970252187_at_[hidden]>
Sent: Friday, June 12, 2026 08:17
To: Tiago Freire <tmiguelf_at_hotmail.com>
Cc: std-discussion_at_[hidden]
Subject: Re: [std-discussion] Does the C++ abstract machine recognize a temporal order of execution?
But there’s nothing else to debate here. We already explained what behavior you can expect with this.
However, the question in my OP is not about observable behavior. I talked about that, for two evaluations `A` and `B`, whether the control flow executes `A` at a point in time that is no later than when it executes `B` is a valid semantics in the abstract machine? Of course, a real implementation doesn't need to emulate the semantics of the abstract machine.
On Fri, Jun 12, 2026 at 2:09 PM Tiago Freire <tmiguelf_at_[hidden]<mailto:tmiguelf_at_[hidden]>> wrote:
> The OP is talking about the semantics and structure in the abstract machine, not only the observable behavior. A possible observable behavior is justified as valid since we infer that from the semantics and structure in the abstract machine. So, talking about whether this is a valid semantics in the abstract machine is necessary.
You already got your answer! That is the answer to what the “abstract machine” is expected to do. What else do you want?
The concept of the “abstract machine” is only about how the code should be interpreted, it is not an emulator that you should create, and it does not define everything.
The “abstract machine” allows for unspecified behavior; but code must run on real machines and on real machines something must always happen.
On some devices the result of the load will always going to be 1, on others it sometimes is going to be 0.
And the “abstract machine” is not going to tell you which one is right, it just shrugs its shoulders and says “yes”. Because different systems do different things, and this is allowed. And this is especially the case for multi-threaded systems.
You can call it an “incomplete non-deterministic abstract machine” if you want to be more exact.
But there’s nothing else to debate here. We already explained what behavior you can expect with this.
All of your questions have been answered.
If you still think that there is still an open question, there’s nothing I can do to help you. My capacity for explaining things is limited and I can’t make it understand it on your behalf.
From: jim x <xmh970252187_at_[hidden]<mailto:xmh970252187_at_[hidden]>>
Sent: Friday, June 12, 2026 04:45
To: Tiago Freire <tmiguelf_at_[hidden]<mailto:tmiguelf_at_[hidden]>>
Cc: std-discussion_at_[hidden]<mailto:std-discussion_at_[hidden]>
Subject: Re: [std-discussion] Does the C++ abstract machine recognize a temporal order of execution?
In your OP example if you find that 'now1 < now2', the result of the atomic load being 0 is a valid outcome.
Yeah, I keep agreeing that this is a valid possible execution in the abstract machine.
I believe you got lost in nuances of distinctions without a difference.
The OP is talking about the semantics and structure in the abstract machine, not only the observable behavior. A possible observable behavior is justified as valid since we infer that from the semantics and structure in the abstract machine.
So, talking about whether this is a valid semantics in the abstract machine is necessary.
On Thu, Jun 11, 2026 at 6:33 PM Tiago Freire <tmiguelf_at_[hidden]<mailto:tmiguelf_at_[hidden]>> wrote:
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]<mailto:std-discussion-bounces_at_[hidden]>> on behalf of jim x via Std-Discussion <std-discussion_at_[hidden]<mailto:std-discussion_at_[hidden]>>
Sent: Thursday, June 11, 2026 11:16:57 AM
To: Jennifier Burnett <jenni_at_[hidden]<mailto:jenni_at_[hidden]>>
Cc: jim x <xmh970252187_at_[hidden]<mailto:xmh970252187_at_[hidden]>>; std-discussion_at_[hidden]<mailto:std-discussion_at_[hidden]> <std-discussion_at_[hidden]<mailto: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
I have already answered this.
From: jim x <xmh970252187_at_[hidden]>
Sent: Friday, June 12, 2026 08:17
To: Tiago Freire <tmiguelf_at_hotmail.com>
Cc: std-discussion_at_[hidden]
Subject: Re: [std-discussion] Does the C++ abstract machine recognize a temporal order of execution?
But there’s nothing else to debate here. We already explained what behavior you can expect with this.
However, the question in my OP is not about observable behavior. I talked about that, for two evaluations `A` and `B`, whether the control flow executes `A` at a point in time that is no later than when it executes `B` is a valid semantics in the abstract machine? Of course, a real implementation doesn't need to emulate the semantics of the abstract machine.
On Fri, Jun 12, 2026 at 2:09 PM Tiago Freire <tmiguelf_at_[hidden]<mailto:tmiguelf_at_[hidden]>> wrote:
> The OP is talking about the semantics and structure in the abstract machine, not only the observable behavior. A possible observable behavior is justified as valid since we infer that from the semantics and structure in the abstract machine. So, talking about whether this is a valid semantics in the abstract machine is necessary.
You already got your answer! That is the answer to what the “abstract machine” is expected to do. What else do you want?
The concept of the “abstract machine” is only about how the code should be interpreted, it is not an emulator that you should create, and it does not define everything.
The “abstract machine” allows for unspecified behavior; but code must run on real machines and on real machines something must always happen.
On some devices the result of the load will always going to be 1, on others it sometimes is going to be 0.
And the “abstract machine” is not going to tell you which one is right, it just shrugs its shoulders and says “yes”. Because different systems do different things, and this is allowed. And this is especially the case for multi-threaded systems.
You can call it an “incomplete non-deterministic abstract machine” if you want to be more exact.
But there’s nothing else to debate here. We already explained what behavior you can expect with this.
All of your questions have been answered.
If you still think that there is still an open question, there’s nothing I can do to help you. My capacity for explaining things is limited and I can’t make it understand it on your behalf.
From: jim x <xmh970252187_at_[hidden]<mailto:xmh970252187_at_[hidden]>>
Sent: Friday, June 12, 2026 04:45
To: Tiago Freire <tmiguelf_at_[hidden]<mailto:tmiguelf_at_[hidden]>>
Cc: std-discussion_at_[hidden]<mailto:std-discussion_at_[hidden]>
Subject: Re: [std-discussion] Does the C++ abstract machine recognize a temporal order of execution?
In your OP example if you find that 'now1 < now2', the result of the atomic load being 0 is a valid outcome.
Yeah, I keep agreeing that this is a valid possible execution in the abstract machine.
I believe you got lost in nuances of distinctions without a difference.
The OP is talking about the semantics and structure in the abstract machine, not only the observable behavior. A possible observable behavior is justified as valid since we infer that from the semantics and structure in the abstract machine.
So, talking about whether this is a valid semantics in the abstract machine is necessary.
On Thu, Jun 11, 2026 at 6:33 PM Tiago Freire <tmiguelf_at_[hidden]<mailto:tmiguelf_at_[hidden]>> wrote:
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]<mailto:std-discussion-bounces_at_[hidden]>> on behalf of jim x via Std-Discussion <std-discussion_at_[hidden]<mailto:std-discussion_at_[hidden]>>
Sent: Thursday, June 11, 2026 11:16:57 AM
To: Jennifier Burnett <jenni_at_[hidden]<mailto:jenni_at_[hidden]>>
Cc: jim x <xmh970252187_at_[hidden]<mailto:xmh970252187_at_[hidden]>>; std-discussion_at_[hidden]<mailto:std-discussion_at_[hidden]> <std-discussion_at_[hidden]<mailto: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-12 06:28:15
