Предположим, у меня есть структура и класс на 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;
}
У меня будут потоки чтения R и один поток писателя. Поток записи обновит ноль или более участников highest_*
. Если поток чтения вызывает get_highs()
, мне нужно, чтобы все записи из текущего вызова функции push_vec()
потока записи были видны потоку чтения до, поток чтения читает highest_x
, highest_y
и т. Д. Для создания вектора .
Теперь я знаю, что если Vec
достаточно мало, я мог бы просто использовать std::atomic<Vec>
. Проблема в том, что если он слишком большой, инструкции собственного процессора для этого хранилища / загрузки не могут быть использованы. Есть ли способ использовать std::atomic_thread_fence
, чтобы гарантировать, что поток записи совершает несколько атомарных операций записи до того, как поток чтения заберет их? То есть гарантия того, что все записи потока записи будут зафиксированы до того, как поток чтения увидит какую-либо из них? Или std::atomic_thread_fence
только обеспечивает гарантии переупорядочения внутри потока? В настоящее время простое использование .store(std::memory_order_release)
для каждого члена, похоже, не гарантирует, что все три сохранения произойдут до любого чтения.
Очевидно, я мог бы использовать здесь блокировку, но в идеале я хочу найти способ сделать эту структуру данных свободной от блокировок.
Я знаю, что могу поместить highest_x
, highest_y
и highest_z
в одну структуру и разместить две ее копии в куче, атомарно меняя местами указатели после каждой записи. Это единственный способ сделать это?