C++ supported atomic thread fences, that is fences guaranteeing properties for thread that use std::atomic<>
operations, with the function atomic_thread_fence
. It takes a memory order parameter to adjust the "strength" of the fence.
I understand that fences are useful when not all atomic operations are done with a "strong" order:
(1) that includes RMW operations
So the usefulness of all these (acquire, release and acq_rel fences) is obvious: they allow threads that use atomic operations weaker than acq/rel (respectively) to synchronize properly.
But I don't understand where memory_order_seq_cst
could be specifically needed as a fence:
What's the implication of using weaker than memory_order_seq_cst
atomic operations and a memory_order_seq_cst
fence?
What would specifically be guaranteed (in term of possible ordering of atomic operations) by a memory_order_seq_cst
fence that wouldn't be guaranteed by memory_order_acq_rel
?
The default is std::memory_order_seq_cst which establishes a single total ordering over all atomic operations tagged with this tag: all threads see the same order of such atomic operations and no memory_order_seq_cst atomic operations can be reordered.
memory_order_acquire. A load operation with this memory order performs the acquire operation on the affected memory location: no reads or writes in the current thread can be reordered before this load.
No, a seq-cst-fence is not only both a release and an acquire-fence, but also provides some additional properties (see Working Draft, Standard for Programming Language C++, 32.4.4-32.4.8). A seq-cst fence is also part of the single total order of all sequentially consistent operations, enforcing the following observations:
memory_order_seq_cst
fence X sequenced before B, then B observes either the last memory_order_seq_cst
modification of M preceding X in the total order S or a later modification of M in its modification order.memory_order_seq_cst
fence X such that A is sequenced before X and B follows X in S, then B observes either the effects of A or a later modification of M in its modification order.memory_order_seq_cst
fences X and Y such that A is sequenced before X, Y is sequenced before B, and X precedes Y in S, then B observes either the effects of A or a later modification of M in its modification order.For example, I am using seq-cst fences in my hazard pointer implementation: https://github.com/mpoeter/xenium/blob/master/xenium/reclamation/impl/hazard_pointer.hpp
The thread acquiring a safe reference to some object uses seq-cst fence after storing the hazard pointer, but before re-reading the pointer to the object. The thread trying to reclaim some objects uses a seq-cst fence before gathering the active hazard pointers from all threads. Based on the rules above this ensures that either the thread trying to reclaim the object sees that some other thread has a HP for this object (i.e., the object is used), or the reload of thread trying to acquire the safe reference to the object returns a different pointer, indicating to that thread that the object has been removed and it has to perform a retry.
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