26 static_assert(std::is_copy_constructible_v<T>,
27 "LatestSnapshot requires a copy-constructible value type");
28 static_assert(std::is_copy_assignable_v<T>,
29 "LatestSnapshot requires a copy-assignable value type");
34 std::is_nothrow_copy_constructible_v<T>)
35 : slots_{initial, initial, initial}
45 void Store(
const T& value)
noexcept(std::is_nothrow_copy_assignable_v<T>)
47 slots_[back_] = value;
49 const uint32_t previous =
50 state_.exchange(Pack(back_,
true), std::memory_order_acq_rel);
51 back_ = Index(previous);
59 bool LoadLatest(T& output)
noexcept(std::is_nothrow_copy_assignable_v<T>)
62 uint32_t observed = state_.load(std::memory_order_acquire);
64 while (HasNew(observed))
66 const uint32_t desired = Pack(front_,
false);
67 if (state_.compare_exchange_weak(observed, desired, std::memory_order_acq_rel,
68 std::memory_order_acquire))
70 front_ = Index(observed);
76 output = slots_[front_];
86 static constexpr uint32_t INDEX_MASK = 0x3U;
87 static constexpr uint32_t HAS_NEW_BIT = 1U << 2U;
89 static constexpr uint32_t Pack(uint32_t index,
bool has_new)
91 return index | (has_new ? HAS_NEW_BIT : 0U);
94 static constexpr uint32_t Index(uint32_t state) {
return state & INDEX_MASK; }
96 static constexpr bool HasNew(uint32_t state) {
return (state & HAS_NEW_BIT) != 0U; }
99 std::atomic<uint32_t> state_{Pack(1U,
false)};
100 uint32_t front_ = 0U;