17#include <sertial/containers/ring_buffer.hpp>
36 static uint64_t
get(
const T& msg) {
42template<
typename PayloadT>
101template<
typename T, std::
size_t MaxSize = 100>
104 static_assert(MaxSize > 0,
"MaxSize must be greater than 0");
119 std::chrono::milliseconds default_tolerance = std::chrono::milliseconds(50)
120 ) : default_tolerance_(default_tolerance) {}
133 return buffer_.size();
151 return buffer_.empty();
161 return buffer_.full();
171 oldest_timestamp_ = 0;
172 newest_timestamp_ = 0;
203 if (buffer_.empty()) {
205 }
else if (buffer_.full()) {
211 buffer_.push_back(message);
228 if (buffer_.empty()) {
230 }
else if (buffer_.full()) {
235 buffer_.push_back(std::move(message));
278 std::chrono::milliseconds tolerance = std::chrono::milliseconds(-1),
283 if (buffer_.empty()) {
288 if (tolerance.count() < 0) {
289 tolerance = default_tolerance_;
294 uint64_t tolerance_ns =
static_cast<uint64_t
>(tolerance.count()) * 1'000'000ULL;
297 uint64_t lower_bound = (timestamp >= tolerance_ns) ? (timestamp - tolerance_ns) : 0;
298 uint64_t upper_bound = timestamp + tolerance_ns;
299 if (upper_bound < timestamp) {
300 upper_bound = UINT64_MAX;
303 if (upper_bound < oldest_timestamp_ || lower_bound > newest_timestamp_) {
310 return getData_nearest(timestamp, tolerance_ns);
312 return getData_before(timestamp, tolerance_ns);
314 return getData_after(timestamp, tolerance_ns);
318 return getData_nearest(timestamp, tolerance_ns);
331 if (buffer_.empty()) {
334 return {oldest_timestamp_, newest_timestamp_};
346 std::optional<T> getData_nearest(uint64_t timestamp, uint64_t tolerance_ns)
const {
347 if (buffer_.empty()) {
355 for (
size_type i = 1; i < buffer_.size(); ++i) {
357 if (diff < best_diff) {
363 if (best_diff <= tolerance_ns) {
364 return buffer_[best_idx];
374 std::optional<T> getData_before(uint64_t timestamp, uint64_t tolerance_units)
const {
375 if (buffer_.empty()) {
380 for (
size_type i = buffer_.size(); i > 0; --i) {
384 if (diff <= tolerance_units) {
398 std::optional<T> getData_after(uint64_t timestamp, uint64_t tolerance_units)
const {
399 if (buffer_.empty()) {
404 for (
size_type i = 0; i < buffer_.size(); ++i) {
407 if (diff <= tolerance_units) {
421 mutable SharedMutex mutex_;
422 sertial::RingBuffer<T, MaxSize> buffer_;
425 uint64_t oldest_timestamp_{0};
426 uint64_t newest_timestamp_{0};
428 std::chrono::milliseconds default_tolerance_;
Thread-safe timestamped ring buffer with getData lookup.
bool full() const
Check if buffer is full.
void push(const T &message)
Push new message with timestamp.
void clear()
Clear all messages from buffer.
bool empty() const
Check if buffer is empty.
std::pair< uint64_t, uint64_t > getTimestampRange() const
Get timestamp range currently in buffer.
static constexpr size_type capacity()
Get maximum capacity.
void push(T &&message)
Push new message via move.
TimestampedRingBuffer(std::chrono::milliseconds default_tolerance=std::chrono::milliseconds(50))
Constructor with optional sync tolerance.
std::optional< T > getData(uint64_t timestamp, std::chrono::milliseconds tolerance=std::chrono::milliseconds(-1), InterpolationMode mode=InterpolationMode::NEAREST) const
size_type size() const
Get current number of stored messages.
CommRaT - Modern C++ Real-Time Communication Framework.
std::shared_lock< SharedMutex > SharedLock
Scoped shared lock (RAII) - for readers.
InterpolationMode
Interpolation mode for timestamp-based lookup.
@ BEFORE
Return message at or before requested timestamp.
@ NEAREST
Return closest message by timestamp.
@ AFTER
Return message at or after requested timestamp.
@ INTERPOLATE
Linear interpolation (if T supports it - future)
std::unique_lock< SharedMutex > UniqueLockShared
Scoped unique lock (RAII) - for writers.
static uint64_t get(const TimsMessage< PayloadT > &msg)
Trait to access timestamp from different message types.
static uint64_t get(const T &msg)
Unified threading and synchronization abstractions for CommRaT.
Unified timestamp and time utility abstractions for CommRaT.