Consider the code below:
// Class member initialization:
std::atomic<bool> ready_ = false;
...
// Core A:
while (!ready_.load(std::memory_order_acquire)) {
// On x86, you would probably put a `pause` instruction here.
}
// Core A now accesses memory written by Core B.
...
// Core B:
// Core B writes memory.
ready_.store(true, std::memory_order_release);
Assume that Core A and Core B are two different physical cores (i.e., they are not two hyperthreads co-located on the same physical core). Does Core A's code above have worse performance than the code below or equal performance? Note that Core A is simply doing a load; this is not the classic compare-exchange example that involves a write. I am interested in the answer for several architectures.
// Core A:
while (!ready_.load(std::memory_order_relaxed)) {
// On x86, you would probably put a `pause` instruction here.
}
std::atomic_thread_fence(std::memory_order_acquire);
// Core A now accesses memory written by Core B.
The mailbox code on this reference page alludes to the bottom code having better performance since the bottom code avoids "unnecessary synchronization." However, the mailbox code is iterating over many atomics, so the synchronization overhead of acquire consistency is a problem since you could use relaxed consistency to avoid ordering constraints on mailboxes that are not yours. It is not clear to me what the performance impact is of spinning on a single acquire load.