Suppose I have a structure and class in C++:
struct Vec {
double x;
double y;
double z;
}
class VecTracker {
Vec latest_vec;
std::atomic<double> highest_x;
std::atomic<double> highest_y;
std::atomic<double> highest_z;
//updates highest_x, highest_y, highest_z atomically
void push_vec(const Vec& v);
double get_high_x() const;
double get_high_y() const;
double get_high_z() const;
//returns Vec consisting of snapshot of highest_x, highest_y, highest_z
Vec get_highs() const;
}
I'll have R reader threads and one writer thread. The writer thread will update zero or more of the highest_* members. If the reader thread calls get_highs() I need all the writes from the current invocation of the writer thread's push_vec() function to be visible to the reader thread before the reader thread reads highest_x, highest_y, etc. to produce a vector.
Now, I know that if Vec is sufficiently small, I could just use a std::atomic<Vec>. Problem is, if it's too big, native CPU instructions for these store/loads can't be used. Is there any way to use std::atomic_thread_fence to guarantee that multiple atomic writes are committed by the writer thread before the reader thread picks them up? That is, a guarantee that all writes by the writer thread are committed before a reader thread sees any of them? Or does std::atomic_thread_fence only provide reordering guarantees within a thread? Currently, just using the .store(std::memory_order_release) for each member doesn't seem to guarantee that all three stores happen before any reads.
Obviously, I could use a lock here, but ideally I want to find a way to make this data structure lockfree.
I know that I could put highest_x, highest_y, and highest_z in a single struct and allocate two copies of it on the heap, swapping pointers atomically after each write. Is this the only way to do it?