102 lines
3.4 KiB
C++
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{};
|
|
};
|
|
}
|