Skip to content

File ring_buffer.hpp

File List > include > loon > ring_buffer.hpp

Go to the documentation of this file

// Copyright (c) 2026 Jorge Suarez-Rivaya
// SPDX-License-Identifier: MIT

#pragma once


#include <array>
#include <cstddef>
#include <optional>

namespace loon {

template <typename T, size_t N>
class RingBuffer {
 public:
  RingBuffer() = default;

  explicit RingBuffer(bool override_when_full) : override(override_when_full) {}

  [[nodiscard]] bool push(const T& value) {
    if (full()) {
      if (!override) {
        return false;
      }
      // advance read pointer to discard oldest
      read = (read + 1) % N;
    } else {
      ++count;
    }
    buffer[write] = value;
    write = (write + 1) % N;

    return true;
  }

  [[nodiscard]] std::optional<T> pop() {
    if (empty()) {
      return std::nullopt;
    }
    T value = buffer[read];
    read = (read + 1) % N;
    --count;
    return value;
  }

  [[nodiscard]] std::optional<T> front() {
    if (empty()) {
      return std::nullopt;
    }
    return buffer[read];
  }

  [[nodiscard]] std::optional<T> back() {
    if (empty()) {
      return std::nullopt;
    }
    return buffer[(write - 1 + N) % N];
  }

  bool discard() {
    if (empty()) {
      return false;
    }
    read = (read + 1) % N;
    --count;
    return true;
  }

  [[nodiscard]] size_t capacity() const { return N; }

  [[nodiscard]] bool empty() const { return count == 0; }

  [[nodiscard]] bool full() const { return count == N; }

  [[nodiscard]] bool overrides() const { return override; }

  [[nodiscard]] size_t size() const { return count; }

 private:
  std::array<T, N> buffer;
  size_t write = 0;
  size_t read = 0;
  size_t count = 0;
  bool override = false;
};

} // namespace loon