std::memory_order
C++‘s enum for controlling which memory reorderings are blocked around an atomic operation. Saw this at Tesla.
What each ordering actually means lives in Memory Consistency Model § Programming against it. This note is just the C++ syntax and idiomatic patterns.
enum memory_order {
memory_order_relaxed, // no ordering, just atomicity
memory_order_consume, // acquire but only for data-dependent reads (rarely used, often promoted to acquire)
memory_order_acquire, // later accesses can't move before this load
memory_order_release, // earlier accesses can't move after this store
memory_order_acq_rel, // both, for RMW ops like fetch_add
memory_order_seq_cst // default: full SC, a single total order across all threads
};Acquire / release pairing
The bread-and-butter pattern, paired load/store on a flag to publish data:
std::atomic<int> flag{0};
int data;
// Thread A
data = 123;
flag.store(1, std::memory_order_release); // data=123 can't float past this
// Thread B
while (flag.load(std::memory_order_acquire) == 0) {}
std::cout << data; // guaranteed to see 123Fences
Same effect, but the fence is separate from the atomic operation so the atomic itself can be relaxed:
std::atomic<int> flag{0};
int data;
void producer() {
data = 123;
std::atomic_thread_fence(std::memory_order_release);
flag.store(1, std::memory_order_relaxed);
}
void consumer() {
while (flag.load(std::memory_order_relaxed) == 0) {}
std::atomic_thread_fence(std::memory_order_acquire);
int x = data; // guaranteed 123
}