update ring buffer
This commit is contained in:
parent
f042e07ee7
commit
8151edeebf
|
@ -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:
|
||||||
|
explicit RingBuffer(size_t capacity)
|
||||||
|
: buffer(capacity), capacity(capacity), head(0), tail(0), full(false) {}
|
||||||
|
|
||||||
bool push(const T &item) {
|
bool push(const T &item) {
|
||||||
size_t current_head = head.load(std::memory_order_relaxed);
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
size_t next_head = (current_head + 1) & (Capacity - 1);
|
if (full) {
|
||||||
|
return false;
|
||||||
if (next_head == tail.load(std::memory_order_acquire)) {
|
|
||||||
return false; // buffer full
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue