Plast interview

27. Acquire-Release Basics

In a low-latency SPSC path publishing quotes, we must ensure data becomes visible to the reader with minimal synchronization. Acquire-release is often the lightest portable guarantee that still prevents subtle reordering. Evaluate the correctness and latency trade-offs of the following pattern.

#include <atomic>
struct Data { int v; };
std::atomic<bool> ready{false};
Data d;
void produce(){ d.v=7; ready.store(true, std::memory_order_release); }
int consume(){ while(!ready.load(std::memory_order_acquire)){} return d.v; }

Part 1.

Does this establish a happens-before that guarantees consume() returns 7 on all platforms? If you changed either side to memory_order_relaxed, what breaks and why?

Part 2.

(1) When is memory_order_relaxed safe in producer or consumer here?

(2) Compare atomic_thread_fence with store/load acquire-release for this pattern.

(3) Could ready false sharing degrade latency? How would you pad or align?

(4) If Data has multiple fields, are torn or stale reads possible? Why?

(5) Is std::atomic<bool> lock-free portable? ABI or alignment considerations?

Answer

Answer (Part 1)

Yes. The store(std::memory_order_release) synchronizes-with the load(std::memory_order_acquire), creating a happens-before edge that makes all prior writes to d visible, so consume() returns 7 without a data race. If either side is memory_order_relaxed, there is no synchronization; the consumer may observe ready == true yet still read a stale d.v due to allowed reordering/visibility.

Answer (Part 2)

(1) Only when additional fences establish ordering, or when the data need not be visible. Producer: release fence + relaxed store; consumer: acquire fence + relaxed load.

(2) Fences order surrounding non-atomic accesses but don’t carry the synchronization through the atomic itself; they’re easier to misuse. Acquire/release on the atomic encodes the edge directly, often compiling to equal or fewer barriers.

(3) Yes, if ready shares a cache line with hot data, coherence traffic spikes. Use alignas(64) or padding to isolate it onto its own line.

(4) Under acquire-release, all writes sequenced-before the release become visible together; you won’t see a mixed snapshot. Avoid unaligned or oversized loads; ensure natural alignment to prevent hardware tearing.

(5) Not guaranteed; is_lock_free is implementation-defined and hardware-dependent. Sub-byte atomics may not be lock-free; ensure proper alignment and consider using a wider atomic type.