Prusa-MMU-Private
PrusaMultiMaterialUpgradev3firmwareforMK3SMK4
circular_buffer.h
Go to the documentation of this file.
1 #pragma once
3 #include <stddef.h>
4 #include "../intlimits.h"
5 
12 template <typename index_t = uint_fast8_t, index_t size = 16>
14 public:
15  static constexpr bool size_is_power2 = !(size & (size - 1));
16 
17  static_assert(size <= std::numeric_limits<index_t>::max() / 2,
18  "index_t is too small for the requested size");
19 
20  constexpr inline CircularIndex()
21  : tail(0)
22  , head(0) {}
23 
25  inline bool empty() const {
26  return tail == head;
27  }
28 
30  inline bool full() const {
31  return count() == size;
32  }
33 
35  inline void reset() {
36  head = tail;
37  }
38 
41  inline void push() {
42  head = next(head);
43  }
44 
47  inline void pop() {
48  tail = next(tail);
49  }
50 
53  inline index_t front() const {
54  return mask(tail);
55  }
56 
59  inline index_t back() const {
60  return mask(head);
61  }
62 
64  inline index_t count() const {
65  if constexpr (size_is_power2)
66  return head - tail;
67  else {
68  return head >= tail
69  ? (head - tail)
70  : (size * 2 + head) - tail;
71  }
72  }
73 
74 protected:
75  index_t tail;
76  index_t head;
77 
79  static index_t mask(index_t cursor) { return cursor % size; }
80 
82  static index_t next(index_t cursor) {
83  // note: the modulo can be avoided if size is a power of two: we can do this
84  // relying on the optimizer eliding the following check at compile time.
85  if constexpr (size_is_power2)
86  return (cursor + 1);
87  else
88  return (cursor + 1) % (size * 2);
89  }
90 };
91 
99 template <typename T = uint8_t, typename index_t = uint_fast8_t, size_t size = 16>
101 public:
102  inline bool empty() const {
103  return index.empty();
104  }
105 
106  bool full() const {
107  return index.full();
108  }
109 
111  inline void reset() {
112  index.reset();
113  }
114 
119  bool push(T elem) {
120  if (full())
121  return false;
122  data[index.back()] = elem;
123  index.push();
124  return true;
125  }
126 
129  inline T front() const {
130  return data[index.front()];
131  }
132 
135  bool pop(T &elem) {
136  if (empty())
137  return false;
138  elem = front();
139  index.pop();
140  return true;
141  }
142 
143  index_t count() const {
144  return index.count();
145  }
146 
147 protected:
148  T data[size];
150 };
Definition: circular_buffer.h:100
CircularIndex< index_t, size > index
circular index
Definition: circular_buffer.h:149
void reset()
Reset the circular buffer to empty.
Definition: circular_buffer.h:111
bool pop(T &elem)
Definition: circular_buffer.h:135
bool push(T elem)
Definition: circular_buffer.h:119
T front() const
Definition: circular_buffer.h:129
T data[size]
array of stored elements
Definition: circular_buffer.h:148
Definition: circular_buffer.h:13
static index_t next(index_t cursor)
Definition: circular_buffer.h:82
index_t tail
cursor of the element to read (pop/extract) from the buffer
Definition: circular_buffer.h:75
index_t head
cursor of the empty spot or element insertion (write)
Definition: circular_buffer.h:76
void reset()
Reset the indexes to empty.
Definition: circular_buffer.h:35
static index_t mask(index_t cursor)
Definition: circular_buffer.h:79
index_t back() const
Definition: circular_buffer.h:59
bool empty() const
Definition: circular_buffer.h:25
index_t count() const
Definition: circular_buffer.h:64
void pop()
Definition: circular_buffer.h:47
index_t front() const
Definition: circular_buffer.h:53
bool full() const
Definition: circular_buffer.h:30
void push()
Definition: circular_buffer.h:41