23#ifndef HF_UTILS_RTOS_WRAP_ERRORHISTORY_H_
24#define HF_UTILS_RTOS_WRAP_ERRORHISTORY_H_
36template <
typename Record>
42 [[nodiscard]] virtual std::
size_t Size() const noexcept = 0;
45 [[nodiscard]] virtual std::
size_t Capacity() const noexcept = 0;
48 [[nodiscard]] virtual uint32_t
Seq() const noexcept = 0;
57 virtual std::
size_t Snapshot(Record* out, std::
size_t max_out) const noexcept = 0;
60template <typename Record>
66 virtual
bool Push(const Record& record) noexcept = 0;
69 virtual
bool Pop(Record& out) noexcept = 0;
72 virtual
bool Clear() noexcept = 0;
75template <typename Record, std::
size_t kCapacity>
80 static_assert(kCapacity > 0,
"ErrorHistory kCapacity must be > 0");
81 static_assert(std::is_trivially_copyable_v<Record>,
82 "ErrorHistory<Record, N> requires a trivially copyable Record");
92 bool Push(const Record& record) noexcept
override
94 std::lock_guard<RtosMutex> guard(mutex_);
95 std::memcpy(&records_[head_], &record,
sizeof(Record));
96 head_ = (head_ + 1U) % kCapacity;
97 if (size_ < kCapacity) {
100 tail_ = (tail_ + 1U) % kCapacity;
107 bool Pop(Record& out)
noexcept override
109 std::lock_guard<RtosMutex> guard(mutex_);
110 if (size_ == 0U)
return false;
111 std::memcpy(&out, &records_[tail_],
sizeof(Record));
112 tail_ = (tail_ + 1U) % kCapacity;
120 std::lock_guard<RtosMutex> guard(mutex_);
121 head_ = tail_ = size_ = 0U;
128 [[nodiscard]] std::size_t
Size() const noexcept
override
130 std::lock_guard<RtosMutex> guard(mutex_);
134 [[nodiscard]] std::size_t
Capacity() const noexcept
override
139 [[nodiscard]] uint32_t
Seq() const noexcept
override
141 std::lock_guard<RtosMutex> guard(mutex_);
147 std::lock_guard<RtosMutex> guard(mutex_);
148 return overwrite_count_;
151 std::size_t
Snapshot(Record* out, std::size_t max_out)
const noexcept override
153 if (out ==
nullptr || max_out == 0U)
return 0U;
154 std::lock_guard<RtosMutex> guard(mutex_);
155 const std::size_t n = (size_ < max_out) ? size_ : max_out;
156 std::size_t idx = tail_;
157 for (std::size_t i = 0; i < n; ++i) {
158 std::memcpy(&out[i], &records_[idx],
sizeof(Record));
159 idx = (idx + 1U) % kCapacity;
166 Record records_[kCapacity]{};
167 std::size_t head_{0};
168 std::size_t tail_{0};
169 std::size_t size_{0};
171 uint32_t overwrite_count_{0};
Cross-platform RTOS mutex and synchronization primitives.
Definition RtosMutex.h:76
Definition ErrorHistory.h:79
std::size_t Snapshot(Record *out, std::size_t max_out) const noexcept override
Copy up to max_out records into out, oldest first.
Definition ErrorHistory.h:151
bool Clear() noexcept override
Drop all records.
Definition ErrorHistory.h:118
std::size_t Capacity() const noexcept override
Maximum number of entries the ring can hold.
Definition ErrorHistory.h:134
uint32_t OverwriteCount() const noexcept override
Number of Push calls that overwrote an older entry.
Definition ErrorHistory.h:145
std::size_t Size() const noexcept override
Number of entries currently held (≤ Capacity()).
Definition ErrorHistory.h:128
uint32_t Seq() const noexcept override
Monotonic counter; bumps on every successful Push / Pop / Clear.
Definition ErrorHistory.h:139
bool Pop(Record &out) noexcept override
Pop oldest record into out; returns false if empty.
Definition ErrorHistory.h:107
ErrorHistory() noexcept=default
Definition ErrorHistory.h:37
virtual std::size_t Size() const noexcept=0
Number of entries currently held (≤ Capacity()).
virtual uint32_t OverwriteCount() const noexcept=0
Number of Push calls that overwrote an older entry.
virtual std::size_t Capacity() const noexcept=0
Maximum number of entries the ring can hold.
virtual uint32_t Seq() const noexcept=0
Monotonic counter; bumps on every successful Push / Pop / Clear.
virtual std::size_t Snapshot(Record *out, std::size_t max_out) const noexcept=0
Copy up to max_out records into out, oldest first.
virtual ~ErrorHistoryReader() noexcept=default
Definition ErrorHistory.h:61
virtual ~ErrorHistoryWriter() noexcept=default
Definition ErrorHistory.h:34