jabyengine/include/PSX/Auxiliary/circular_buffer.hpp

71 lines
2.5 KiB
C++

#ifndef __JABYENGINE_CIRCULAR_BUFFER_HPP__
#define __JABYENGINE_CIRCULAR_BUFFER_HPP__
#include "array_range.hpp"
namespace JabyEngine {
template<typename T, uint32_t ElementCount>
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;
size_t setup(T* buffer_start_adr) {
this->start_adr = buffer_start_adr;
this->read_idx = 0;
this->write_idx = 0;
return (sizeof(T)*ElementCount);
}
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<T> 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<T> 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__