What does "strongly happens before" mean?
Why was "strongly happens before" introduced? Intuitively, what's its difference and relation with "happens before"?
Brace yourself for "simply happens-before" as well!Take a look at this current snapshot of cpprefhttps://en.cppreference.com/w/cpp/atomic/memory_order
It seems "simply happens-before" is added in C++20.
Simply happens-before
Regardless of threads, evaluation A simply happens-before evaluation B if any of the following is true:
1) A is sequenced-before B
2) A synchronizes-with B
3) A simply happens-before X, and X simply happens-before B
Note: without consume operations, simply happens-before and happens-before relations are the same.
So Simply-HB and HB are the same except for how they handle consume operations. See HB
Happens-before
Regardless of threads, evaluation A happens-before evaluation B if any of the following is true:
1) A is sequenced-before B
2) A inter-thread happens before B
The implementation is required to ensure that the happens-before relation is acyclic, by introducing additional synchronization if necessary (it can only be necessary if a consume operation is involved, see Batty et al)
How do they differ with regard to consume? See Inter-Thread-HB
Inter-thread happens-before
Between threads, evaluation A inter-thread happens before evaluation B if any of the following is true
1) A synchronizes-with B
2) A is dependency-ordered before B
3) ...
...
An operation that is dependency ordered (i.e. uses release/consume) is HB but not necessarily Simply-HB.
Consume is more relaxed than acquire, so if I understand correctly, HB is more relaxed than Simply-HB.
Strongly happens-before
Regardless of threads, evaluation A strongly happens-before evaluation B if any of the following is true:
1) A is sequenced-before B
2) A synchronizes with B, and both A and B are sequentially consistent atomic operations
3) A is sequenced-before X, X simply happens-before Y, and Y is sequenced-before B
4) A strongly happens-before X, and X strongly happens-before B
Note: informally, if A strongly happens-before B, then A appears to be evaluated before B in all contexts.
Note: strongly happens-before excludes consume operations.
So a release/consume operation cannot be Strongly-HB.
Release/acquire can be HB and Simply-HB (because release/acquire synchronizes-with) but is not necessarily Strongly-HB. Because Strongly-HB specifically says that A must synchronize-with B AND be a Sequentially Consistent operation.
Is happens-before guaranteed? HB Simply-HB Strongly-HBrelaxed no no norelease/consume yes no no release/acquire yes yes noS.C. yes yes yes
What does the "A appears to be evaluated before B in all contexts" in the note mean?
All contexts: All threads / all CPUs see (or "will eventually agree on") the same order. This is the guarantee of sequential consistency--a global total modification order of all variables. Acquire/release chains only guarantee perceived modification order for threads participating in the chain. Threads outside the chain are theoretically allowed to see a different order.
I do not know why Strongly-HB and Simply-HB were introduced. Maybe to help clarify how to operate around consume? Strongly-HB has a nice properties--if one thread observes A strongly-happens-before B, it knows all threads will observe the same thing.
The history of consume:
Paul E. McKenney is responsible for consume being in the C and C++ standards. Consume guarantees ordering between pointer assignment and the memory it points to. It was invented because of the DEC Alpha. The DEC Alpha could speculatively dereference a pointer, thus it also had a memory fence to prevent this. The DEC Alpha is no longer made and no processors today have this behavior. Consume is intended to be very relaxed.