// SafeC Standard Library — Lock-Free Ring Buffer (real-time audio / DSP safe)
// Single-producer / single-consumer; power-of-two capacity; no dynamic allocation.
// Uses atomic load/store for head and tail to guarantee correct ordering.
// Freestanding-safe.
#pragma once
#define RING_DEFAULT_CAP 4096 // bytes; override before including if needed
namespace std {
struct RingBuffer {
[]unsigned char buf; // backing store (set by RingBuffer::over)
unsigned long cap; // capacity in bytes (must be power of two)
unsigned long mask; // cap - 1
volatile unsigned long head; // write position (producer)
volatile unsigned long tail; // read position (consumer)
// Initialise over an existing backing store, which must outlive the ring
// (a static array, typically); its length is rounded down to a power of
// two for the capacity.
static struct RingBuffer over([]unsigned char buf);
// Return number of bytes currently readable.
unsigned long length() const;
// Return number of bytes that can be written without blocking.
unsigned long writable() const;
// Return 1 if empty.
int is_empty() const;
// Return 1 if full.
int is_full() const;
// Write as much of `data` as fits. Returns bytes actually written.
unsigned long write([]const unsigned char data);
// Read up to out.len bytes into `out`. Returns bytes actually read.
unsigned long read([]unsigned char out);
// Like read, without consuming. Returns bytes copied.
unsigned long peek([]unsigned char out) const;
// One byte at a time (the Fifo protocol, std/collections/traits.h):
// enqueue returns 1, or 0 if full; dequeue returns null if empty.
int enqueue(unsigned char b);
?unsigned char dequeue();
// Discard `len` bytes. Returns bytes discarded.
unsigned long discard(unsigned long len);
// Reset (empty) the buffer. Safe only when no concurrent access.
void clear();
};
// Static-capacity helper: declares a RingBuffer backed by a static array of `N` bytes.
// Usage: RING_STATIC(my_ring, 1024);
#ifdef __SAFEC_COMPAT_PREPROCESSOR__ // function-like macro: compat mode only
#define RING_STATIC(name, N) \
static unsigned char name##_storage_[N]; \
static struct RingBuffer name = { name##_storage_, N, N-1, 0, 0 }
#endif
} // namespace std