update ring buffer

This commit is contained in:
zongor 2025-07-24 00:16:52 -04:00
parent f042e07ee7
commit 8151edeebf
3 changed files with 71 additions and 53 deletions

View File

@ -1,50 +1,70 @@
#ifndef RING_BUFFER_H #ifndef RING_BUFFER_H
#define RING_BUFFER_H #define RING_BUFFER_H
#include <array> #include <mutex>
#include <atomic> #include <optional>
#include <cstddef> #include <vector>
template <typename T, size_t Capacity> template <typename T> class RingBuffer {
class RingBuffer { std::vector<T> buffer;
static_assert((Capacity & (Capacity - 1)) == 0, "Capacity must be power of 2"); size_t capacity;
size_t head;
size_t tail;
bool full;
private: mutable std::mutex mtx;
std::array<T, Capacity> buffer; bool empty_unlocked() const { return (!full && (head == tail)); }
std::atomic<size_t> head = 0; // write index
std::atomic<size_t> tail = 0; // read index
public: public:
bool push(const T& item) { explicit RingBuffer(size_t capacity)
size_t current_head = head.load(std::memory_order_relaxed); : buffer(capacity), capacity(capacity), head(0), tail(0), full(false) {}
size_t next_head = (current_head + 1) & (Capacity - 1);
if (next_head == tail.load(std::memory_order_acquire)) { bool push(const T &item) {
return false; // buffer full std::lock_guard<std::mutex> lock(mtx);
if (full) {
return false;
} }
buffer[current_head] = item; buffer[tail] = item;
head.store(next_head, std::memory_order_release); tail = (tail + 1) % capacity;
full = (tail == head);
return true; return true;
} }
bool pop(T& item) { std::optional<T> pop() {
size_t current_tail = tail.load(std::memory_order_relaxed); std::lock_guard<std::mutex> lock(mtx);
if (current_tail == head.load(std::memory_order_acquire)) {
return false; // buffer empty if (empty_unlocked()) {
return std::nullopt;
} }
item = buffer[current_tail]; T item = buffer[head];
tail.store((current_tail + 1) & (Capacity - 1), std::memory_order_release); full = false;
return true; head = (head + 1) % capacity;
} }
bool empty() const { bool empty() const {
return head.load() == tail.load(); std::lock_guard<std::mutex> lock(mtx);
return empty_unlocked();
} }
bool full() const { bool full_() const {
return ((head.load() + 1) & (Capacity - 1)) == tail.load(); std::lock_guard<std::mutex> lock(mtx);
return full;
}
size_t size() const {
std::lock_guard<std::mutex> lock(mtx);
if (full) {
return capacity;
}
if (tail >= head) {
return tail - head;
}
return capacity + tail - head;
} }
}; };

View File

@ -4,29 +4,27 @@
#include <thread> #include <thread>
std::atomic<bool> running(true); std::atomic<bool> running(true);
RingBuffer<Vec3, 64> snapshot_buffer; RingBuffer<Vec3> snapshot_buffer(128);
void simulation_loop(std::shared_ptr<SimulationState> state) { void simulation_loop(std::shared_ptr<SimulationState> state) {
Vec3 velocity(0.01, 0.02, 0.03); Vec3 velocity(0.01, 0.02, 0.03);
while (running) { while (running) {
// Update position
for (auto &p : state->positions) { for (auto &p : state->positions) {
p += velocity; p += velocity;
} }
// Push latest position to buffer while (snapshot_buffer.push(state->positions[0])) {
if (!snapshot_buffer.push(state->positions[0])) { std::this_thread::yield();
std::cerr << "Snapshot buffer full, dropping frame\n";
} }
} }
} }
void render_loop() { void render_loop() {
Vec3 latest;
while (running) { while (running) {
while (snapshot_buffer.pop(latest)) {
Vec3 latest;
while (latest = snapshot_buffer.pop()) {
std::cout << "[Render] "; std::cout << "[Render] ";
latest.print(); latest.print();
} }

View File

@ -13,7 +13,7 @@ struct SimulationState {
}; };
extern std::atomic<bool> running; extern std::atomic<bool> running;
extern RingBuffer<Vec3, 64> snapshot_buffer; extern RingBuffer<Vec3> snapshot_buffer;
void simulation_loop(std::shared_ptr<SimulationState> state); void simulation_loop(std::shared_ptr<SimulationState> state);
void render_loop(); void render_loop();