After seeing Herb Sutters excellent talk about "atomic weapons" I got a bit confused about the Relaxed Atomics examples.
I took with me that an atomic in the C++ Memory Model (SC-DRF = Sequentially Consistent for Data Race Free) does an "acquire" on a load/read.
I understand that for a load [and a store] the default is std::memory_order_seq_cst
and therefore the two are the same:
myatomic.load(); // (1)
myatomic.load(std::memory_order_seq_cst); // (2)
So far so good, no Relaxed Atomics involved (and after hearing the talk I will never to use the relaxed ones. Ever. Promise. But when someone asks me, I might have to explain...).
But why is it the "relaxed" semantics when I use
myatomic.load(std::memory_order_acquire); // (3)
Since load is acquiring and not releasing, why is this different from (1)
and (2)
? What actually is relaxed here?
The only thing I can think of is that I misunderstood that load means acquire. And if that is true, and the default seq_cst
means both, doesn't that mean a full fence -- nothing can pass up that instruction, nor down? I have to have misunderstood that part.
[and symmetrically for store and release].
It can be a bit confusing to call myatomic.load(std::memory_order_acquire);
a "relaxed atomic" load, since there is a std::memory_order_relaxed
. Some people describe any order weaker than seq_cst
as "relaxed".
You're right to note that sequentially-consistent load is an acquire load, but it has an additional requirement: sequentially-consistent load is also a part of the total global order for all seq_cst operations.
It comes into play when you're dealing with more than one atomic variable: individual modification orders of two atomics may appear in different relative order to different threads, unless sequential consistency is imposed.