77 lines
1.8 KiB
C
77 lines
1.8 KiB
C
#include "ringbuffer.h"
|
|
#include <stdlib.h>
|
|
|
|
static inline size_t load_head(const RingBuf *r) {
|
|
return atomic_load_explicit(&r->head, memory_order_relaxed);
|
|
}
|
|
static inline size_t load_tail(const RingBuf *r) {
|
|
return atomic_load_explicit(&r->tail, memory_order_relaxed);
|
|
}
|
|
static inline void store_head(RingBuf *r, size_t v) {
|
|
atomic_store_explicit(&r->head, v, memory_order_relaxed);
|
|
}
|
|
static inline void store_tail(RingBuf *r, size_t v) {
|
|
atomic_store_explicit(&r->tail, v, memory_order_relaxed);
|
|
}
|
|
|
|
int ring_init(RingBuf *r, size_t capacity) {
|
|
r->buf = (float *)malloc(capacity * sizeof(float));
|
|
if (!r->buf)
|
|
return -1;
|
|
r->capacity = capacity;
|
|
store_head(r, 0);
|
|
store_tail(r, 0);
|
|
return 0;
|
|
}
|
|
|
|
void ring_destroy(RingBuf *r) {
|
|
free(r->buf);
|
|
r->buf = NULL;
|
|
r->capacity = 0;
|
|
}
|
|
|
|
static size_t ring_readable(const RingBuf *r) {
|
|
size_t h = load_head(r);
|
|
size_t t = load_tail(r);
|
|
if (h >= t)
|
|
return h - t;
|
|
else
|
|
return r->capacity - (t - h);
|
|
}
|
|
|
|
static size_t ring_writeable(const RingBuf *r) {
|
|
return r->capacity - 1 - ring_readable(r);
|
|
}
|
|
|
|
size_t ring_write(RingBuf *r, const float *data, size_t count) {
|
|
size_t avail = ring_writeable(r);
|
|
if (count > avail)
|
|
count = avail;
|
|
if (count == 0)
|
|
return 0;
|
|
size_t head = load_head(r);
|
|
size_t cap = r->capacity;
|
|
for (size_t i = 0; i < count; ++i) {
|
|
r->buf[head] = data[i];
|
|
head = (head + 1) % cap;
|
|
}
|
|
store_head(r, head);
|
|
return count;
|
|
}
|
|
|
|
size_t ring_read(RingBuf *r, float *data, size_t count) {
|
|
size_t avail = ring_readable(r);
|
|
if (count > avail)
|
|
count = avail;
|
|
if (count == 0)
|
|
return 0;
|
|
size_t tail = load_tail(r);
|
|
size_t cap = r->capacity;
|
|
for (size_t i = 0; i < count; ++i) {
|
|
data[i] = r->buf[tail];
|
|
tail = (tail + 1) % cap;
|
|
}
|
|
store_tail(r, tail);
|
|
return count;
|
|
}
|