CodePudding user response:
An evaluation which is sequenced-before another evaluation also happens-before it.
Sequenced-before is a relation between evaluations in the same thread and independent of synchronization mechanism like e.g. atomic load/stores with non-relaxed memory orders.
Happens-before just extends the sequenced-before relation for evaluation order from the single-threaded case to the multi-threaded case by incorporating synchronization mechanisms between threads.
See https://en.cppreference.com/w/cpp/atomic/memory_order for exact definitions.
An evaluation in one statement preceding another statement is always sequenced-before the latter. (Basically there is a sequence point between two statements, although that term is not used anymore since C 11.)
The compiler can reorder the two relaxed stores. That doesn't affect the happens-before relation though. Just because two stores (on different atomics) happen-before one another does not imply that the stores can't be observed in a different order by another thread, as demonstrated by the example in the diagram.
You would need to establish a happens-before relation between the loads and stores to prevent the shown outcome. And for that inter-thread ordering in some way is required, e.g. via release/acquire atomic operations. Basically, you would need to establish some arrow betweeen the gray boxes in the diagram.