#pragma once #include #include #include #include // left_right based on // https://github.com/pramalhe/ConcurrencyFreaks/blob/master/papers/left-right-2014.pdf // see concurrencyfreaks.com namespace left_right { template struct left_right { template void update(Func &&f) { std::lock_guard lock(write_mutex); auto cur = current.load(); auto next = (cur + 1) & 1; while (readers[next] != 0) std::this_thread::yield(); f(data[next]); current = next; while (readers[cur] != 0) std::this_thread::yield(); f(data[cur]); } T read() { auto cur = current.load(); for (;;) { readers[cur] += 1; auto cur_ = current.load(); if (cur_ == cur) break; readers[cur] -= 1; cur = cur_; } auto val = data[cur]; readers[cur] -= 1; return val; } private: std::atomic_uint_fast8_t current; std::atomic_long readers[2]; std::mutex write_mutex; T data[2] = {{}, {}}; }; }