libxr  1.0
Want to be the best embedded framework
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
23template <typename T>
25{
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");
30
31 public:
33 explicit LatestSnapshot(const T& initial) noexcept(
34 std::is_nothrow_copy_constructible_v<T>)
35 : slots_{initial, initial, initial}
36 {
37 }
38
45 void Store(const T& value) noexcept(std::is_nothrow_copy_assignable_v<T>)
46 {
47 slots_[back_] = value;
48
49 const uint32_t previous =
50 state_.exchange(Pack(back_, true), std::memory_order_acq_rel);
51 back_ = Index(previous);
52 }
53
59 bool LoadLatest(T& output) noexcept(std::is_nothrow_copy_assignable_v<T>)
60 {
61 bool updated = false;
62 uint32_t observed = state_.load(std::memory_order_acquire);
63
64 while (HasNew(observed))
65 {
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))
69 {
70 front_ = Index(observed);
71 updated = true;
72 break;
73 }
74 }
75
76 output = slots_[front_];
77 return updated;
78 }
79
80 LatestSnapshot(const LatestSnapshot&) = delete;
81 LatestSnapshot& operator=(const LatestSnapshot&) = delete;
83 LatestSnapshot& operator=(LatestSnapshot&&) = delete;
84
85 private:
86 static constexpr uint32_t INDEX_MASK = 0x3U;
87 static constexpr uint32_t HAS_NEW_BIT = 1U << 2U;
88
89 static constexpr uint32_t Pack(uint32_t index, bool has_new)
90 {
91 return index | (has_new ? HAS_NEW_BIT : 0U);
92 }
93
94 static constexpr uint32_t Index(uint32_t state) { return state & INDEX_MASK; }
95
96 static constexpr bool HasNew(uint32_t state) { return (state & HAS_NEW_BIT) != 0U; }
97
98 T slots_[3];
99 std::atomic<uint32_t> state_{Pack(1U, false)};
100 uint32_t front_ = 0U;
101 uint32_t back_ = 2U;
102};
103
104} // namespace LibXR
SPSC mailbox retaining only the latest fully published value.
LatestSnapshot(const T &initial) noexcept(std::is_nothrow_copy_constructible_v< T >)
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 >)
Copy the latest complete value into output.
LibXR 命名空间
Definition ch32_can.hpp:14