update ring buffer
This commit is contained in:
parent
f042e07ee7
commit
8151edeebf
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue