ringbuffer.hpp 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #pragma once
  2. // A simple ringbuffer holding Size elements of type T
  3. template <typename T, uint8_t Size>
  4. class RingBuffer {
  5. protected:
  6. T buf_[Size];
  7. uint8_t head_{0}, tail_{0};
  8. public:
  9. inline uint8_t nextPosition(uint8_t position) {
  10. return (position + 1) % Size;
  11. }
  12. inline uint8_t prevPosition(uint8_t position) {
  13. if (position == 0) {
  14. return Size - 1;
  15. }
  16. return position - 1;
  17. }
  18. inline bool enqueue(const T &item) {
  19. static_assert(Size > 1, "RingBuffer size must be > 1");
  20. uint8_t next = nextPosition(head_);
  21. if (next == tail_) {
  22. // Full
  23. return false;
  24. }
  25. buf_[head_] = item;
  26. head_ = next;
  27. return true;
  28. }
  29. inline bool get(T &dest, bool commit = true) {
  30. auto tail = tail_;
  31. if (tail == head_) {
  32. // No more data
  33. return false;
  34. }
  35. dest = buf_[tail];
  36. tail = nextPosition(tail);
  37. if (commit) {
  38. tail_ = tail;
  39. }
  40. return true;
  41. }
  42. inline bool empty() const {
  43. return head_ == tail_;
  44. }
  45. inline uint8_t size() const {
  46. int diff = head_ - tail_;
  47. if (diff >= 0) {
  48. return diff;
  49. }
  50. return Size + diff;
  51. }
  52. inline T &front() {
  53. return buf_[tail_];
  54. }
  55. inline bool peek(T &item) {
  56. return get(item, false);
  57. }
  58. };