Files
netcode-demo/common/include/common/ring_buffer.hpp
2026-01-11 01:37:39 +04:00

78 lines
2.1 KiB
C++

#pragma once
#include <array>
#include <optional>
#include <cstddef>
namespace netcode {
template<typename T, size_t Capacity>
class RingBuffer {
public:
void push(const T& item) {
data_[write_index_] = item;
write_index_ = (write_index_ + 1) % Capacity;
if (count_ < Capacity) {
count_++;
} else {
read_index_ = (read_index_ + 1) % Capacity;
}
}
std::optional<T> pop() {
if (count_ == 0) return std::nullopt;
T item = data_[read_index_];
read_index_ = (read_index_ + 1) % Capacity;
count_--;
return item;
}
const T* peek() const {
if (count_ == 0) return nullptr;
return &data_[read_index_];
}
const T* at(size_t index) const {
if (index >= count_) return nullptr;
size_t actual_index = (read_index_ + index) % Capacity;
return &data_[actual_index];
}
T* at(size_t index) {
if (index >= count_) return nullptr;
size_t actual_index = (read_index_ + index) % Capacity;
return &data_[actual_index];
}
// Доступ по sequence number (для команд)
template<typename SeqGetter>
const T* find_by_sequence(uint32_t seq, SeqGetter getter) const {
for (size_t i = 0; i < count_; ++i) {
const T* item = at(i);
if (item && getter(*item) == seq) {
return item;
}
}
return nullptr;
}
void clear() {
read_index_ = 0;
write_index_ = 0;
count_ = 0;
}
size_t size() const { return count_; }
bool empty() const { return count_ == 0; }
bool full() const { return count_ == Capacity; }
static constexpr size_t capacity() { return Capacity; }
private:
std::array<T, Capacity> data_;
size_t read_index_ = 0;
size_t write_index_ = 0;
size_t count_ = 0;
};
} // namespace netcode