Another developer has shown me the following snippet:
std::atomic_flag lock;
// ...
while (lock.test_and_set(std::memory_order::acquire)) {}
// critical section
lock.clear(std::memory_order::release);
I'm confused about what specifying acquire
as the memory order does here.
Is this implicitly the same order as acq_rel
, or is it acquire
for the load operation and seq_cst
(the default) for the store operation within this read-modify-write operation?
std::atomic_flag::test_and_set
has no preconditions and it is merely said that:
Memory is affected according to the value of
order
.
That doesn't clarify things for me. What if order
is acquire
? How is the store affected then, huh?
Memory orders are (only) described in terms of their effect on synchronization and sequencing.
An atomic operation
A
that performs a release operation on an atomic objectM
synchronizes with an atomic operationB
that performs an acquire operation onM
and takes its value from any side effect in the release sequence headed byA
.
The effect of the acquire
on the "test" part of test_and_set
is obvious. As for its effect on the "set" part? Well, it doesn't have one. As with relaxed
, there's simply no useful guarantees the standard provides. So it's equivalent to something like memory_order::acq_relaxed
. The compiler is free to move read/writes downward past the test_and_set
, but not to move them upward.