#ifndef __JABYENGINE_CIRCULAR_BUFFER_HPP__ #define __JABYENGINE_CIRCULAR_BUFFER_HPP__ #include "array_range.hpp" namespace JabyEngine { template class FastCircularBuffer { private: T* start_adr = nullptr; size_t read_idx = 0; size_t write_idx = 0; static size_t increment(size_t cur_idx, size_t step) { return ((cur_idx + step) & (ElementCount - 1)); } public: FastCircularBuffer() = default; void setup(T* buffer_start_adr) { this->start_adr = buffer_start_adr; this->read_idx = 0; this->write_idx = 0; } T* allocate() { const auto new_idx = FastCircularBuffer::increment(this->write_idx, 1); if(new_idx != this->read_idx) { auto* dst = (this->start_adr + this->write_idx); this->write_idx = new_idx; return dst; } return nullptr; } const T* pop() { if(this->write_idx != this->read_idx) { const auto* src = (this->start_adr + this->read_idx); FastCircularBuffer::drop(1); return src; } return nullptr; } void drop(size_t elements) { this->read_idx = FastCircularBuffer::increment(this->read_idx, elements); } constexpr ArrayRange get_first_continious() const { return {&this->start_adr[this->read_idx], (this->write_idx >= this->read_idx) ? (this->write_idx - this->read_idx) : (ElementCount - this->read_idx)}; } constexpr ArrayRange get_second_continious() const { return {this->start_adr, (this->write_idx < this->read_idx) ? this->write_idx : 0}; } constexpr bool has_data() const { return (this->read_idx != this->write_idx); } static_assert(ElementCount == 2 || ElementCount == 4 || ElementCount == 8 || ElementCount == 16 || ElementCount == 32 || ElementCount == 64 || ElementCount == 128 || ElementCount == 256, "ElementCount for FastCircularBuffer must be power of 2"); }; } #endif //!__JABYENGINE_CIRCULAR_BUFFER_HPP__