I am currently reading Concurrency in Action and on page 111 it gives this sample code relating to a std::atomic_flag
in order to explain how memory orderings work:
f.clear(std::memory_order_release);
bool x = f.test_and_set();
but all it says is:
Here, the call to
clear()
explicitly requests that the flag is cleared with release semantics, while the call totest_and_set()
uses the default memory ordering for setting the flag and retrieving the old value.
They haven't actually explained what the differences are. Could somebody provide a general overview of how these memory orderings work? So not just the one I have mentioned above, but I believe there are a few more:
memory_order_relaxed
memory_order_release
memory_order_seq_cst
memory_order_consume
memory_order_acquire
memory_order_acq_rel
Informal characterisation (take it with a sack of salt):
Example (atomic operations marked with their memory order on parenthesis):
t1: t2:
data = foo while not data_valid; (ACQUIRE)
data_valid = true; (RELEASE) bar = data;
rcu_derefence()
takes care of inserting a read barrier on Alpha between the read of the pointer and its dereference. Note that there has been some talk on totally changing the specification of the consume memory order (on a mailing list thread called "arch: atomic rework"), as it seems to be impractical for compiler writers. In particular, the current standard allows you to publish p
, and *(q + (p-p))
is dependant on that. Some people contend that makes no sense at all.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With