blob: cd7872e353d5850e00a9818f6e1db4e4ee273576 [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#ifndef AOS_RING_BUFFER_H_
2#define AOS_RING_BUFFER_H_
Parker Schuhecd057f2017-03-11 20:03:01 -08003
4#include <array>
5
6namespace aos {
7
8// This is a helper to keep track of some amount of recent data. As you push
9// data into the ring buffer, it gets stored. If the buffer becomes full, it
10// will start overwriting the oldest data.
11template <typename Data, size_t buffer_size>
12class RingBuffer {
13 public:
Parker Schuhfea48582017-03-11 20:15:32 -080014 static constexpr size_t kBufferSize = buffer_size;
15
James Kuszmaul97f750d2019-01-20 20:08:03 -080016 constexpr RingBuffer() {}
Parker Schuhecd057f2017-03-11 20:03:01 -080017
18 // Add an item to the RingBuffer, overwriting the oldest element if necessary
19 void Push(const Data &data) {
20 if (full()) {
21 data_[oldest_] = data;
22 oldest_ = (oldest_ + 1) % buffer_size;
23 } else {
24 data_[(oldest_ + size_) % buffer_size] = data;
25 ++size_;
26 }
27 }
28
Parker Schuh208a58d2017-04-12 20:51:38 -070029 void Shift() {
30 oldest_ = (oldest_ + 1) % buffer_size;
31 --size_;
32 }
33
Parker Schuhecd057f2017-03-11 20:03:01 -080034 // Return the value of the index requested, adjusted so that the RingBuffer
Parker Schuh208a58d2017-04-12 20:51:38 -070035 // contains the oldest element first and the newest last.
Parker Schuhecd057f2017-03-11 20:03:01 -080036 Data &operator[](size_t index) {
37 return data_[(oldest_ + index) % buffer_size];
38 }
39
40 const Data &operator[](size_t index) const {
41 return data_[(oldest_ + index) % buffer_size];
42 }
43
44 // Returns the capacity of the RingBuffer
45 size_t capacity() const { return buffer_size; }
46
47 // Returns the number of elements stored in the RingBuffer
48 size_t size() const { return size_; }
49
50 // Is the RingBuffer empty or full?
51 bool empty() const { return size_ == 0; }
52
53 bool full() const { return size_ == buffer_size; }
54
Austin Schuhd85c66e2017-04-16 10:50:33 -070055 // Clears all the data out of the buffer.
56 void Reset() { size_ = 0; }
57
Austin Schuh39f7ae92019-04-14 17:14:50 -070058 class iterator {
59 public:
60 using iterator_category = ::std::forward_iterator_tag;
61 using value_type = Data;
62 using difference_type = ::std::ptrdiff_t;
63 using pointer = Data *;
64 using reference = Data &;
65
66 explicit iterator(RingBuffer *buffer, size_t index)
67 : buffer_(buffer), index_(index) {}
68
69 iterator &operator++() {
70 ++index_;
71 return *this;
72 }
73 iterator operator++(int) {
74 iterator retval = *this;
75 ++(*this);
76 return retval;
77 }
78 bool operator==(iterator other) const {
79 return buffer_ == other.buffer_ && index_ == other.index_;
80 }
81 bool operator!=(iterator other) const { return !(*this == other); }
82 reference operator*() const { return (*buffer_)[index_]; }
83
84 private:
85 RingBuffer *buffer_;
86 size_t index_;
87 };
88
89 class const_iterator {
90 public:
91 using iterator_category = ::std::forward_iterator_tag;
92 using value_type = Data;
93 using difference_type = ::std::ptrdiff_t;
94 using pointer = Data *;
95 using reference = Data &;
96
97 explicit const_iterator(const RingBuffer *buffer, size_t index)
98 : buffer_(buffer), index_(index) {}
99
100 const_iterator &operator++() {
101 ++index_;
102 return *this;
103 }
104 const_iterator operator++(int) {
105 const_iterator retval = *this;
106 ++(*this);
107 return retval;
108 }
109 bool operator==(const_iterator other) const {
110 return buffer_ == other.buffer_ && index_ == other.index_;
111 }
112 bool operator!=(const_iterator other) const { return !(*this == other); }
113 const Data &operator*() const { return (*buffer_)[index_]; }
114
115 private:
116 const RingBuffer *buffer_;
117 size_t index_;
118 };
119
120 iterator begin() { return iterator(this, 0); }
121 iterator end() { return iterator(this, size()); }
122
123 const_iterator begin() const { return const_iterator(this, 0); }
124 const_iterator end() const { return const_iterator(this, size()); }
125
Parker Schuhecd057f2017-03-11 20:03:01 -0800126 private:
127 ::std::array<Data, buffer_size> data_;
128
129 // Oldest contains the oldest item added to the RingBuffer which will be the
130 // next one to be overwritten
131 size_t oldest_ = 0;
132 size_t size_ = 0;
133};
134
135} // namespace aos
136
John Park33858a32018-09-28 23:05:48 -0700137#endif // AOS_RING_BUFFER_H_