Skip to content

Instantly share code, notes, and snippets.

@floooh
Last active June 20, 2019 04:11
Show Gist options
  • Save floooh/3eb289cf298e855078b81cad6ac7626d to your computer and use it in GitHub Desktop.
Save floooh/3eb289cf298e855078b81cad6ac7626d to your computer and use it in GitHub Desktop.
simple circular-queue / ringbuffer in C
#define MAX_SLOTS (256)
typedef struct {
uint32_t head; // next slot to enqeue
uint32_t tail; // next slot to dequeue
uint32_t num; // number of slots in ring buffer (plus 1 for empty/full detection)
uint32_t buf[MAX_SLOTS]; // items could be index-handles
} ring_t;
// wrapped index into buf (private helper)
static void _ring_wrap(const ring_t* rb, uint32_t i) {
return i % rb->num;
}
// initialize a ring_t struct
void ring_init(ring_t* rb, uint32_t num_slots) {
assert(rb && (num_slots > 0) && (num_slots < MAX_SLOTS));
memset(rb, 0, sizeof(ring_t));
// one slot reserved to detect full vs empty
rb->num = num_slots + 1;
}
// return true if ring buffer is full
bool ring_full(const ring_t* rb) {
assert(rb && (rb->num > 0));
return _ring_wrap(rb, rb->head + 1) == rb->tail;
}
// return true if ring buffer is empty
bool ring_empty(const ring_t* rb) {
assert(rb && (rb->num > 0));
return rb->head == rb->tail;
}
// return number of items in ring buffer
uint32_t ring_count(const ring_t* rb) {
assert(rb && (rb->num > 0));
uint32_t count;
if (rb->head >= rb->tail) {
count = rb->head - rb->tail;
}
else {
count = (rb->head + rb->num) - rb->tail;
}
assert(count < rb->num);
return count;
}
// enqueue a new item at the front (assumes not full)
bool ring_enqueue(ring_t* rb, uint32_t val) {
assert(rb && (rb->num > 0));
assert(!ring_full(rb));
assert(rb->head < rb->num);
rb->buf[rb->head] = val;
rb->head = _ring_wrap(rb, rb->head + 1);
}
// dequeue item from the back (assumes not empty)
uint32_t ring_dequeue(ring_t* rb) {
assert(rb && (rb->num > 0));
assert(!ring_empty(rb));
assert(rb->tail < rb->num);
uint32_t val = rb->buf[rb->tail];
rb->tail = _ring_wrap(rb, rb->tail + 1);
return val;
}
// return item at relative index (for iterating over content)
uint32_t ring_peek(const ring_t* rb, uint32_t index) {
assert(rb && (rb->num > 0));
assert(index < ring_count(rb));
uint32_t rb_index = _ring_wrap(rb, rb->tail + index);
return rb->buf[rb_index];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment