I was reading about memory orders in C++. I could understand relaxed and acquire-release models a well. But I'm struggling with sequential-consistency.
If I am not wrong, from cppreference, std::memory_order_seq_cst
'operation' is equivalent to:
But what is the case with std::memory_order_seq_cst
'fence'? Is it equivalent to which of these?
If it is equivalent to one of above, what about the other two?
As far as I know, if it is case 1 (acquire fence), compilers would be free to move any write operation from above the fence to below it. Similarly, if it is case 2 (release fence), compilers would be free to move any read operation from below the fence to above it. Finally, if it is case 3 (acq-rel fence), compilers would be disallowed to move any instructions across the fence. Is this correct?
I'm still in a lot of confusion. Above statements may be incorrect. Please correct me where I'm wrong.
In short, it's case 3.
A seq_cst
fence includes all the functionality of an acq_rel
fence. See [atomics.fences p5.5]:
is a sequentially consistent acquire and release fence, if
order == memory_order::seq_cst
.
So in particular it is an acquire and release fence. And it is also a sequentially consistent fence, meaning that it is included in the total order S defined in [atomics.order p4], in a manner consistent with the rules stated there.
The formal C++ memory model does not have a concept of "reordering". However, you are right that a typical implementation of a seq_cst
fence would be one which prevents loads and stores from being reordered across it in either direction. Note that this is strictly stronger than an acq_rel
fence, which would permit a store before the fence to be reordered with a load after the fence (StoreLoad reordering).