libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
latest_snapshot.hpp
1#pragma once
2
3#include <atomic>
4#include <cstdint>
5#include <type_traits>
6
7namespace LibXR
8{
9
37template <typename T>
39{
40 static_assert(std::is_copy_constructible_v<T>,
41 "LatestSnapshot requires a copy-constructible value type");
42 static_assert(std::is_copy_assignable_v<T>,
43 "LatestSnapshot requires a copy-assignable value type");
44
45 public:
53 explicit LatestSnapshot(const T& initial) noexcept(
54 std::is_nothrow_copy_constructible_v<T>)
55 : slots_{initial, initial, initial}
56 {
57 }
58
70 void Store(const T& value) noexcept(std::is_nothrow_copy_assignable_v<T>)
71 {
72 slots_[back_] = value;
73
74 const uint32_t previous =
75 state_.exchange(Pack(back_, true), std::memory_order_acq_rel);
76 back_ = Index(previous);
77 }
78
92 bool LoadLatest(T& output) noexcept(std::is_nothrow_copy_assignable_v<T>)
93 {
94 bool updated = false;
95 uint32_t observed = state_.load(std::memory_order_acquire);
96
97 while (HasNew(observed))
98 {
99 const uint32_t desired = Pack(front_, false);
100 if (state_.compare_exchange_weak(observed, desired, std::memory_order_acq_rel,
101 std::memory_order_acquire))
102 {
103 front_ = Index(observed);
104 updated = true;
105 break;
106 }
107 }
108
109 output = slots_[front_];
110 return updated;
111 }
112
121
122 private:
123 static constexpr uint32_t INDEX_MASK = 0x3U;
124 static constexpr uint32_t HAS_NEW_BIT = 1U << 2U;
125
126 static constexpr uint32_t Pack(uint32_t index, bool has_new)
127 {
128 return index | (has_new ? HAS_NEW_BIT : 0U);
129 }
130
131 static constexpr uint32_t Index(uint32_t state) { return state & INDEX_MASK; }
132
133 static constexpr bool HasNew(uint32_t state) { return (state & HAS_NEW_BIT) != 0U; }
134
135 T slots_[3];
136 // 低两位是中间槽的下标,HAS_NEW_BIT 表示中间槽中有消费者尚未取走的发布。
137 // The low two bits index the middle slot; HAS_NEW_BIT marks a publication the consumer
138 // has not taken yet.
139 std::atomic<uint32_t> state_{Pack(1U, false)};
140 uint32_t front_ = 0U;
141 uint32_t back_ = 2U;
142};
143
144} // namespace LibXR
只保留最新一份完整值的单生产者、单消费者邮箱 / Single-producer, single-consumer mailbox that keeps only the latest complete...
LatestSnapshot(LatestSnapshot &&)=delete
禁止移动构造 / Non-movable
LatestSnapshot & operator=(LatestSnapshot &&)=delete
禁止移动赋值 / Non-move-assignable
LatestSnapshot(const T &initial) noexcept(std::is_nothrow_copy_constructible_v< T >)
用同一个初始值构造三个槽 / Construct all three slots with the same initial value
void Store(const T &value) noexcept(std::is_nothrow_copy_assignable_v< T >)
发布一个完整的值 / Publish one complete value
bool LoadLatest(T &output) noexcept(std::is_nothrow_copy_assignable_v< T >)
把最新的完整值拷入 output / Copy the latest complete value into output
LatestSnapshot(const LatestSnapshot &)=delete
禁止拷贝构造 / Non-copyable
LatestSnapshot & operator=(const LatestSnapshot &)=delete
禁止拷贝赋值 / Non-copy-assignable
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14