C++ Logo

std-discussion

Advanced search

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

From: Jennifier Burnett <jenni_at_[hidden]>
Date: Thu, 11 Jun 2026 22:03:20 +0100
> There would be one thread doing a store-release in the background, which these two threads would synchronise with.

Right, but that doesn't help with synchronising anything practical. It just ensures that if the read of the time point reads a particular value it ensures that any subsequent operations happen-before any operations prior to the release. Since we're modeling the release thread as doing nothing except incrementing the counter there is nothing for the subsequent operations to have a happens-before relationship with (except perhaps the prior increments, but that's rather useless), so the acquire would be equivalent to relaxed.

> I meant that if you can tell that x was stored to, then it must have been stored a value lesser than or equal to TIME().

I think it's maybe just poorly formulated then - you need to both detect the value written flag and then ensure that if the flag is set you read the correct value from the dependent field, which you need to use acquire-release for. Since this is a thought experiment you can just declare that certain reads observe a particular value, so

```
T1:
  x = TIME()
  y.store(x,relaxed)
T2:
  z = y.load(relaxed) //reads x
  assert(z <= TIME())
```

should work fine at demonstrating the problem. The issue is that you need to formulate a way of letting TIME establish a happens-before relationship with the other call through the two relaxed operations, which are only related by the coherence-ordered-before relation. Having an acquire barrier before reading the time point and a release barrier after would do the trick, and declaring that TIME acts as an acq_rel fence would also work as a shortcut. Both of those work by upgrading the surrounding relaxed operations to be tantamount to acq_rel, though, which you may or may not think is a reasonable cost.

On 11 June 2026 20:47:00 BST, Thiago Macieira <thiago_at_[hidden]> wrote:
>On Thursday, 11 June 2026 10:52:33 Pacific Daylight Time Jennifier Burnett
>wrote:
>> Do just want to point out that the proposed barrier isn't a standard c++
>> acquire barrier but a new magic barrier that would need new semantics, c++
>> acquires are meaningless without a corresponding release (since it only
>> establishes a happens-before between things after the acquire and things
>> before the release) and so would do nothing, or could only synchronise with
>> the incrementing thread as you said before.
>
>There would be one thread doing a store-release in the background, which these
>two threads would synchronise with.
>
>> ```
>>
>> T1:
>> temp = TIME()
>> <load-store barrier>
>> y.store(1, relaxed)
>> x.store(temp, relaxed)
>>
>> T2:
>> w = x.load(relaxed)
>> z = y.load(relaxed)
>> <load-load barrier>
>> temp = TIME()
>> if (z) assert(w <= temp)
>>
>> ```
>>
>> Which allows reading z == 1, w == INT64_MAX.
>
>I agree. I wasn't precise in my wording.
>
>I meant that if you can tell that x was stored to, then it must have been
>stored a value lesser than or equal to TIME(). That's the other assertion I
>said:
>
> assert(w == INT64_MAX || w <= TIME());
>
>Specifically, we should be seeing:
>
>x = INT64_MAX
>y = 0
>now = arbitrary value away from INT64_MAX
>
>T1:
> temp = TIME() // a.k.a. now.load(acquire)
> x.store(temp, relaxed)
> y.store(1, relaxed)
>
>T2:
> temp1 = x.load(relaxed)
> temp2 = y.load(relaxed)
> temp3 = TIME() // a.k.a. now.load(acquire)
> assert(temp1 == INT64_MAX || temp1 <= temp3)
> if (temp2)
> assert(temp1 <= temp3)
>
>Timing thread:
> while (1) {
> nanosleep(1);
> now.fetch_add(1, release)
> }
>
>In this scenario, I think we can be certain the first assertion is always true.
>The now.load() in T1 happens-before the store to x in that thread (a younger
>load or store cannot bypass a the barrier) and the x.load() in T2 happens-
>before the now.load() (an older load cannot bypass the barrier). Therefore, if
>temp1 != INT64_MAX, then temp3 cannot be a value less than temp1.
>
>The second assertion is not necessary, as you said. But this is now entirely
>inside of the control of the programmer and should simply be developed to use
>proper lock-free atomic semantics.
>

Received on 2026-06-11 21:03:30