I've read this Q&A: What is the significance of 'strongly happens before' compared to '(simply) happens before'?
The author gives an outline of an interesting evaluation that was not possible until C++20 but apparently is possible starting C++20:
.-- T3 y.store(3, seq_cst); --. (2)
| | | strongly
| | sequenced before | happens
| V | before
| T3 a = x.load(seq_cst); // a = 0 --. <-' (3)
| : coherence-
| : ordered
| : before
| T1 x.store(1, seq_cst); <-' --. --. (4)
| | |st |
| | sequenced before |h |
| V |b |
| . T1 y.store(1, release); <-' | (x)
| | : | strongly
| | : synchronizes with | happens
| | V | before
| > T2 b = y.fetch_add(1, seq_cst); // b = 1 --. | (1)
| | |st |
| | sequenced before |h |
| V |b |
'-> T2 c = y.load(relaxed); // c = 3 <-' <-'
The numbers on the right denote a possible seq_cst
order (and I added (x) for convenience; this line does not participate in SC order since it's not an SC operation).
I was trying to understand what is the modification order of y
in this example, but I don't know how to determine it. (Or are there multiple possible modification orders of y
for this evaluation?..)
More generally, how is modification order of an atomic variable defined in C++? For example there's this: https://en.cppreference.com/w/cpp/atomic/memory_order
Write-write coherence: If evaluation A that modifies some atomic M (a write) happens-before evaluation B that modifies M, then A appears earlier than B in the modification order of M
So it seems that modification order has to be consistent with a write-write happens-before one.
Is it the only thing that defines modification order?
In the above example, AFAIU there's no happens-before between (2) and (1); so which one is first in the modification order of y
?
Is the mod order of y
(x 1 2) (for this evaluation)?
I believe it might also help reasoning about seq_cst
order...