A lock-free single-producer single-consumer ring buffer keeps `head` and `tail` indices. Even with correct atomics, throughput is poor. The single most effective layout fix is:
struct Ring {
std::atomic<size_t> head; // written by consumer
std::atomic<size_t> tail; // written by producer
T buffer[N];
};