17#ifndef MBED_CIRCULARBUFFER_H
18#define MBED_CIRCULARBUFFER_H
21#include "platform/mbed_critical.h"
22#include "platform/mbed_assert.h"
23#include "platform/Span.h"
24#include "platform/mbed_atomic.h"
32 static const bool value =
false;
36 static const bool value =
true;
40 static const bool value =
true;
44 static const bool value =
true;
48 static const bool value =
true;
52 static const bool value =
true;
68template<
typename T, u
int32_t BufferSize,
typename CounterType = u
int32_t>
75 "CounterType must be unsigned"
79 (
sizeof(CounterType) >=
sizeof(uint32_t)) ||
80 (BufferSize < (((uint64_t) 1) << (
sizeof(CounterType) * 8))),
81 "Invalid BufferSize for the CounterType"
97 _buffer[_head] = data;
99 _head = incrementCounter(_head);
103 }
else if (_head == _tail) {
115 void push(
const T *src, CounterType len)
122 if (len > BufferSize) {
126 std::copy(src + len - BufferSize, src + len, _buffer);
129 bool adjust_tail = ((BufferSize - non_critical_size()) <= len);
131 CounterType written = len;
134 if ((_head + written) > BufferSize) {
135 written = BufferSize - _head;
138 std::copy(src, src + written, _buffer + _head);
139 _head = incrementCounter(_head, written);
141 CounterType left_to_write = len - written;
145 std::copy(src + written, src + written + left_to_write, _buffer);
146 _head = left_to_write;
174 bool data_popped =
false;
178 if (!non_critical_empty()) {
181 data = _buffer[_tail];
182 _tail = incrementCounter(_tail);
199 CounterType
pop(T *dest, CounterType len)
207 CounterType data_popped = 0;
211 if (!non_critical_empty()) {
213 if (len > non_critical_size()) {
214 len = non_critical_size();
219 if ((_tail + data_popped) > BufferSize) {
220 data_popped = BufferSize - _tail;
223 std::copy(_buffer + _tail, _buffer + _tail + data_popped, dest);
224 _tail = incrementCounter(_tail, data_popped);
227 CounterType left_to_pop = len - data_popped;
230 std::copy(_buffer, _buffer + left_to_pop, dest + data_popped);
233 data_popped += left_to_pop;
253 CounterType popped =
pop(dest.
data(), dest.
size());
264 bool is_empty = non_critical_empty();
275 return core_util_atomic_load_bool(&_full);
296 CounterType elements = non_critical_size();
308 bool data_updated =
false;
311 data = _buffer[_tail];
319 bool non_critical_empty()
const
321 bool is_empty = (_head == _tail) && !_full;
325 CounterType non_critical_size()
const
327 CounterType elements;
330 elements = BufferSize + _head - _tail;
332 elements = _head - _tail;
335 elements = BufferSize;
346 CounterType incrementCounter(CounterType val, CounterType increment = 1)
352 if (val == BufferSize) {
360 T _buffer[BufferSize];
Templated Circular buffer class.
CounterType pop(T *dest, CounterType len)
Pop multiple elements from the buffer.
void push(const T *src, CounterType len)
Push the transaction to the buffer.
void push(mbed::Span< const T > src)
Push the transaction to the buffer.
mbed::Span< T > pop(mbed::Span< T > dest)
Pop multiple elements from the buffer.
CounterType size() const
Get the number of elements currently stored in the circular_buffer.
bool empty() const
Check if the buffer is empty.
bool pop(T &data)
Pop from the buffer.
bool peek(T &data) const
Peek into circular buffer without popping.
bool full() const
Check if the buffer is full.
void push(const T &data)
Push the transaction to the buffer.
void reset()
Reset the buffer.
Nonowning view to a sequence of contiguous elements.
pointer data() const
Return a pointer to the first element of the sequence or NULL if the Span is empty().
index_type size() const
Return the size of the sequence viewed.