My Project
ring_buffer.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cassert>
4 #include <stdexcept>
5 #include <vector>
6 
7 namespace cpu_mlp {
8 
15 template <typename T> class RingBuffer {
16 public:
21  explicit RingBuffer(size_t capacity = 0) : _capacity(capacity), _head(0), _count(0) {
22  if (_capacity > 0) {
23  _data.resize(_capacity);
24  }
25  }
26 
31  void set_capacity(size_t capacity) {
32  _capacity = capacity;
33  _data.resize(capacity);
34  _head = 0;
35  _count = 0;
36  }
37 
43  void push_back(const T &val) {
44  if (_capacity == 0) return; // Or throw? For now silent no-op or assert.
45 
46  if (_count < _capacity) {
47  // Not full: append at (_head + _count) % _capacity
48  // Since _head is usually 0 initially, this fills sequentially.
49  // But if we erased (not supported here) or wrapped, we must be careful.
50  // For this simple implementation:
51  size_t insert_idx = (_head + _count) % _capacity;
52  _data[insert_idx] = val;
53  _count++;
54  } else {
55  // Full: overwrite head, and move head forward
56  _data[_head] = val;
57  _head = (_head + 1) % _capacity;
58  }
59  }
60 
61  // Access by logical index: 0 is oldest, size()-1 is newest
67  T &operator[](size_t i) {
68  assert(i < _count);
69  return _data[(_head + i) % _capacity];
70  }
71 
77  const T &operator[](size_t i) const {
78  assert(i < _count);
79  return _data[(_head + i) % _capacity];
80  }
81 
86  T &back() {
87  assert(_count > 0);
88  return (*this)[_count - 1];
89  }
90 
95  const T &back() const {
96  assert(_count > 0);
97  return (*this)[_count - 1];
98  }
99 
101  size_t size() const { return _count; }
102 
104  bool empty() const { return _count == 0; }
105 
107  bool full() const { return _count == _capacity; }
108 
112  void clear() {
113  _count = 0;
114  _head = 0;
115  }
116 
117  // For convenience, to mimic vector::reserve (though we use resizing in constructor)
122  void reserve(size_t n) {
123  if (n > _capacity) {
124  set_capacity(n); // Warning: this clears data in my simple implementation!
125  // LBFGS usually sets size once.
126  }
127  }
128 
129 private:
130  std::vector<T> _data;
131  size_t _capacity;
132  size_t _head; // Index of the oldest element
133  size_t _count; // Current number of elements
134 };
135 
136 } // namespace cpu_mlp
A fixed-capacity ring buffer (circular buffer).
Definition: ring_buffer.hpp:15
void set_capacity(size_t capacity)
Resizes and resets the buffer.
Definition: ring_buffer.hpp:31
bool empty() const
Checks if the buffer is empty.
Definition: ring_buffer.hpp:104
void clear()
Clears the buffer content.
Definition: ring_buffer.hpp:112
void push_back(const T &val)
Pushes a new element into the buffer.
Definition: ring_buffer.hpp:43
size_t size() const
Returns the number of elements currently stored.
Definition: ring_buffer.hpp:101
const T & operator[](size_t i) const
Construct element by logical index (0 is oldest).
Definition: ring_buffer.hpp:77
T & operator[](size_t i)
Access element by logical index (0 is oldest).
Definition: ring_buffer.hpp:67
const T & back() const
Access the newest element (const).
Definition: ring_buffer.hpp:95
bool full() const
Checks if the buffer is full.
Definition: ring_buffer.hpp:107
RingBuffer(size_t capacity=0)
Constructs a RingBuffer with a given capacity.
Definition: ring_buffer.hpp:21
void reserve(size_t n)
Reserve capacity (resets buffer if new capacity > old capacity).
Definition: ring_buffer.hpp:122
T & back()
Access the newest element.
Definition: ring_buffer.hpp:86
Definition: layer.hpp:13