Files
Renderive/Core/architecture/Bounded_Input_Buffer.h
T
2026-08-01 20:09:45 +08:00

102 lines
3.4 KiB
C++

#pragma once
#include <algorithm>
#include <array>
#include <atomic>
#include <cstdint>
#include <memory_resource>
#include <optional>
#include <span>
#include <utility>
#include <vector>
#include "../base/Memory.h"
#include "Psc_Cpp_Core/Base/RingBuffer.hpp"
namespace renderive {
class Bounded_Input_Buffer {
public:
void push(const void* data, std::size_t size, std::size_t max_packet_count) {
configure(size, max_packet_count);
while (!buffer.write(data, size)) {
if (!buffer.skip_one())
return;
}
}
template <typename Handler>
void read_all(Handler handler) {
std::size_t packet_size{};
while (buffer.peek_len(packet_size)) {
read_buffer.resize(packet_size);
std::size_t read_size = packet_size;
if (!buffer.read(read_buffer.data(), read_size))
return;
handler(read_buffer.data(), read_size);
}
}
void clear() {
while (buffer.skip_one()) {}
}
private:
void configure(std::size_t max_packet_size, std::size_t max_packet_count) {
max_packet_count = std::max<std::size_t>(1, max_packet_count);
max_packet_size = std::max<std::size_t>(1, max_packet_size);
if (Initialized && max_packet_size <= this->max_packet_size && max_packet_count == this->max_packet_count)
return;
this->max_packet_size = max_packet_size;
this->max_packet_count = max_packet_count;
buffer.init((Psc::RingBuffer_ST::HEADER_SIZE + max_packet_size) * max_packet_count);
Initialized = true;
}
bool Initialized = false;
std::size_t max_packet_size{};
std::size_t max_packet_count{};
Psc::RingBuffer_ST buffer{memory_resource(Memory_Domain::Input_Buffer)};
std::pmr::vector<std::uint8_t> read_buffer{memory_resource(Memory_Domain::Input_Buffer)};
};
class Bounded_Vector_Double_Input_Buffer {
public:
void push(std::span<const double> data, std::size_t max_packet_count) {
prepare_push(max_packet_count);
std::pmr::vector<double>& row = row_at(row_count);
row.assign(data.begin(), data.end());
++row_count;
}
void push(std::pmr::vector<double>&& data, std::size_t max_packet_count) {
prepare_push(max_packet_count);
rows[row_count].emplace(std::move(data));
++row_count;
}
template <typename Handler>
void read_all(Handler handler) {
for (std::size_t i = 0; i < row_count; ++i)
handler(*rows[i]);
row_count = 0;
}
void clear() {
row_count = 0;
}
private:
static constexpr std::size_t Storage_Count = 64;
std::pmr::vector<double>& row_at(std::size_t index) {
if (!rows[index])
rows[index].emplace(memory_resource(Memory_Domain::Input_Buffer));
return *rows[index];
}
void prepare_push(std::size_t max_packet_count) {
max_packet_count = std::clamp<std::size_t>(max_packet_count, 1, Storage_Count);
while (row_count >= max_packet_count)
drop_front();
}
void drop_front() {
if (!row_count)
return;
rows[0].reset();
for (std::size_t i = 1; i < row_count; ++i) {
rows[i - 1].emplace(std::move(*rows[i]));
rows[i].reset();
}
--row_count;
}
std::array<std::optional<std::pmr::vector<double>>, Storage_Count> rows;
std::size_t row_count{};
};
}