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

View File

@ -4,33 +4,31 @@
#include <thread>
std::atomic<bool> running(true);
RingBuffer<Vec3, 64> snapshot_buffer;
RingBuffer<Vec3> snapshot_buffer(128);
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) {
// Update position
for (auto &p : state->positions) {
p += velocity;
}
// Push latest position to buffer
if (!snapshot_buffer.push(state->positions[0])) {
std::cerr << "Snapshot buffer full, dropping frame\n";
}
while (running) {
for (auto &p : state->positions) {
p += velocity;
}
while (snapshot_buffer.push(state->positions[0])) {
std::this_thread::yield();
}
}
}
void render_loop() {
Vec3 latest;
while (running) {
while (running) {
while (snapshot_buffer.pop(latest)) {
std::cout << "[Render] ";
latest.print();
}
// Optional: add very short pause to avoid spinning too fast
std::this_thread::yield(); // cooperative multitasking
Vec3 latest;
while (latest = snapshot_buffer.pop()) {
std::cout << "[Render] ";
latest.print();
}
// Optional: add very short pause to avoid spinning too fast
std::this_thread::yield(); // cooperative multitasking
}
}

View File

@ -13,7 +13,7 @@ struct SimulationState {
};
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 render_loop();