106 lines
2.5 KiB
C++
106 lines
2.5 KiB
C++
#pragma once
|
|
|
|
#include <span>
|
|
|
|
#include "lock.h"
|
|
|
|
struct RingBuffer {
|
|
std::span<std::byte> buffer;
|
|
|
|
size_t read_ptr = 0;
|
|
size_t write_ptr = 0;
|
|
size_t used = 0;
|
|
|
|
bool Store(std::span<const std::byte> data) {
|
|
InterruptLock lock;
|
|
|
|
if (data.size() > FreeSpace()) {
|
|
return false;
|
|
}
|
|
const size_t to_copy = std::min(buffer.size() - write_ptr, data.size());
|
|
std::copy(data.begin(), data.begin() + to_copy,
|
|
buffer.begin() + write_ptr);
|
|
if (to_copy < data.size()) {
|
|
std::copy(data.begin() + to_copy, data.end(), buffer.begin());
|
|
}
|
|
Push(data.size());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Load(std::span<std::byte> out) {
|
|
InterruptLock lock;
|
|
|
|
if (out.size() > AvailableData()) {
|
|
return false;
|
|
}
|
|
const size_t to_copy = std::min(buffer.size() - read_ptr, out.size());
|
|
std::copy(buffer.begin() + read_ptr,
|
|
buffer.begin() + read_ptr + to_copy, out.begin());
|
|
if (to_copy < out.size()) {
|
|
std::copy(buffer.begin(), buffer.begin() + out.size() - to_copy,
|
|
out.begin() + to_copy);
|
|
}
|
|
Pop(out.size());
|
|
return true;
|
|
}
|
|
|
|
bool Push(size_t amount) {
|
|
InterruptLock lock;
|
|
|
|
if (amount > FreeSpace()) {
|
|
return false;
|
|
}
|
|
write_ptr = (write_ptr + amount) % buffer.size();
|
|
used = used + amount;
|
|
return true;
|
|
}
|
|
|
|
bool Pop(size_t amount) {
|
|
InterruptLock lock;
|
|
|
|
if (amount > AvailableData()) {
|
|
return false;
|
|
}
|
|
read_ptr = (read_ptr + amount) % buffer.size();
|
|
used = used - amount;
|
|
return true;
|
|
}
|
|
|
|
size_t FreeSpace() const {
|
|
InterruptLock lock;
|
|
|
|
return buffer.size() - used;
|
|
}
|
|
|
|
size_t AvailableData() const {
|
|
InterruptLock lock;
|
|
|
|
return used;
|
|
}
|
|
|
|
uint8_t* RawReadPointer() const {
|
|
InterruptLock lock;
|
|
|
|
return reinterpret_cast<uint8_t*>(buffer.data() + read_ptr);
|
|
}
|
|
|
|
uint8_t* RawWritePointer() const {
|
|
InterruptLock lock;
|
|
|
|
return reinterpret_cast<uint8_t*>(buffer.data() + write_ptr);
|
|
}
|
|
|
|
size_t ContiguousFreeSpace() const {
|
|
InterruptLock lock;
|
|
|
|
return std::min(FreeSpace(), buffer.size() - write_ptr);
|
|
}
|
|
|
|
size_t ContiguousAvailableData() const {
|
|
InterruptLock lock;
|
|
|
|
return std::min(AvailableData(), buffer.size() - read_ptr);
|
|
}
|
|
};
|