Search code examples
c++atomicstdatomicmemory-barriers

Can an atomic release be "overwritten"?


Say I have atomic<int> i; Thread A performs an atomic store/exchange with memory_order_release. Next, Thread B performs an atomic store with memory_order_release. Thread C performs an atomic fetch_add(0, memory_order_acquire);

Does Thread C acquire dependencies from thread A and B or only thread B?


Solution

  • Only B (I'm going to assume that by "next" you mean the modification order of the atomic is A -> B -> C so that by [atomics.order]p11 C's RMW must read the value B wrote). See the note in [intro.races]p6:

    Except in the specified cases, reading a later value does not necessarily ensure visibility as described below. Such a requirement would sometimes interfere with efficient implementation.

    The read part of the fetch_add is an acquire operation that took its value from the store-release, so the store release synchronizes with the RMW by [atomics.order]p2:

    An atomic operation A that performs a release operation on an atomic object M synchronizes with an atomic operation B that performs an acquire operation on M and takes its value from any side effect in the release sequence headed by A.

    However, the store/release performed by thread B is not an RMW operation and therefore is not part of the release sequence headed by thread A's store (see [intro.races]p5). Therefore, thread A's store doesn't synchronize with the fetch_add.