47 static_assert(std::atomic<std::uint8_t>::is_always_lock_free,
48 "TripleBuffer publication flags must be lock-free");
54 buffers_[0] = initial;
55 buffers_[1] = initial;
56 buffers_[2] = initial;
62 void write(
const T& value)
noexcept(std::is_nothrow_copy_assignable_v<T>) {
64 [&value](T& back)
noexcept(std::is_nothrow_copy_assignable_v<T>) { back = value; });
72 template <
typename Fill>
73 void write_with(Fill&& fill)
noexcept(
noexcept(std::declval<Fill>()(std::declval<T&>()))) {
74 [[maybe_unused]]
const RoleGuard guard(active_roles_, kWriterRole);
75 std::forward<Fill>(fill)(buffers_[back_]);
80 const auto previous = middle_.exchange(
static_cast<std::uint8_t
>(back_ | kDirtyBit),
81 std::memory_order_acq_rel);
82 back_ = previous & kIndexMask;
89 [[maybe_unused]]
const RoleGuard guard(active_roles_, kReaderRole);
90 if (middle_.load(std::memory_order_relaxed) & kDirtyBit) {
91 const auto previous = middle_.exchange(front_, std::memory_order_acq_rel);
92 front_ = previous & kIndexMask;
94 return buffers_[front_];
102 static constexpr std::uint8_t kDirtyBit = 0x80;
103 static constexpr std::uint8_t kIndexMask = 0x03;
108 static constexpr std::uint8_t kWriterRole = 0x01;
109 static constexpr std::uint8_t kReaderRole = 0x02;
112 RoleGuard(std::atomic<std::uint8_t>& roles, std::uint8_t role) noexcept
113 : roles_(roles), role_(role) {
114 const auto before = roles_.fetch_or(role_, std::memory_order_acquire);
115 assert((before & role_) == 0 &&
"TripleBuffer: two overlapping calls in the same role");
119 roles_.fetch_and(
static_cast<std::uint8_t
>(~role_), std::memory_order_release);
121 std::atomic<std::uint8_t>& roles_;
124 RoleGuard(std::atomic<std::uint8_t>&, std::uint8_t)
noexcept {}
128 std::array<T, 3> buffers_{};
129 std::atomic<std::uint8_t> middle_{1};
130 std::uint8_t back_ = 0;
131 std::uint8_t front_ = 2;
132 std::atomic<std::uint8_t> active_roles_{0};
void write_with(Fill &&fill) noexcept(noexcept(std::declval< Fill >()(std::declval< T & >())))
Fill and publish the writer-owned back buffer in place.
Definition triple_buffer.hpp:73
void write(const T &value) noexcept(std::is_nothrow_copy_assignable_v< T >)
Publish a new value from the writer thread.
Definition triple_buffer.hpp:62