blob: cd7872e353d5850e00a9818f6e1db4e4ee273576 [file] [log] [blame]
#ifndef AOS_RING_BUFFER_H_
#define AOS_RING_BUFFER_H_
#include <array>
namespace aos {
// This is a helper to keep track of some amount of recent data. As you push
// data into the ring buffer, it gets stored. If the buffer becomes full, it
// will start overwriting the oldest data.
template <typename Data, size_t buffer_size>
class RingBuffer {
public:
static constexpr size_t kBufferSize = buffer_size;
constexpr RingBuffer() {}
// Add an item to the RingBuffer, overwriting the oldest element if necessary
void Push(const Data &data) {
if (full()) {
data_[oldest_] = data;
oldest_ = (oldest_ + 1) % buffer_size;
} else {
data_[(oldest_ + size_) % buffer_size] = data;
++size_;
}
}
void Shift() {
oldest_ = (oldest_ + 1) % buffer_size;
--size_;
}
// Return the value of the index requested, adjusted so that the RingBuffer
// contains the oldest element first and the newest last.
Data &operator[](size_t index) {
return data_[(oldest_ + index) % buffer_size];
}
const Data &operator[](size_t index) const {
return data_[(oldest_ + index) % buffer_size];
}
// Returns the capacity of the RingBuffer
size_t capacity() const { return buffer_size; }
// Returns the number of elements stored in the RingBuffer
size_t size() const { return size_; }
// Is the RingBuffer empty or full?
bool empty() const { return size_ == 0; }
bool full() const { return size_ == buffer_size; }
// Clears all the data out of the buffer.
void Reset() { size_ = 0; }
class iterator {
public:
using iterator_category = ::std::forward_iterator_tag;
using value_type = Data;
using difference_type = ::std::ptrdiff_t;
using pointer = Data *;
using reference = Data &;
explicit iterator(RingBuffer *buffer, size_t index)
: buffer_(buffer), index_(index) {}
iterator &operator++() {
++index_;
return *this;
}
iterator operator++(int) {
iterator retval = *this;
++(*this);
return retval;
}
bool operator==(iterator other) const {
return buffer_ == other.buffer_ && index_ == other.index_;
}
bool operator!=(iterator other) const { return !(*this == other); }
reference operator*() const { return (*buffer_)[index_]; }
private:
RingBuffer *buffer_;
size_t index_;
};
class const_iterator {
public:
using iterator_category = ::std::forward_iterator_tag;
using value_type = Data;
using difference_type = ::std::ptrdiff_t;
using pointer = Data *;
using reference = Data &;
explicit const_iterator(const RingBuffer *buffer, size_t index)
: buffer_(buffer), index_(index) {}
const_iterator &operator++() {
++index_;
return *this;
}
const_iterator operator++(int) {
const_iterator retval = *this;
++(*this);
return retval;
}
bool operator==(const_iterator other) const {
return buffer_ == other.buffer_ && index_ == other.index_;
}
bool operator!=(const_iterator other) const { return !(*this == other); }
const Data &operator*() const { return (*buffer_)[index_]; }
private:
const RingBuffer *buffer_;
size_t index_;
};
iterator begin() { return iterator(this, 0); }
iterator end() { return iterator(this, size()); }
const_iterator begin() const { return const_iterator(this, 0); }
const_iterator end() const { return const_iterator(this, size()); }
private:
::std::array<Data, buffer_size> data_;
// Oldest contains the oldest item added to the RingBuffer which will be the
// next one to be overwritten
size_t oldest_ = 0;
size_t size_ = 0;
};
} // namespace aos
#endif // AOS_RING_BUFFER_H_