From 69c9b2c9cab6c1ef6ae4ba7f26d53480ae919ffb Mon Sep 17 00:00:00 2001 From: Midgard Date: Wed, 29 Jan 2020 14:45:48 +0100 Subject: [PATCH] Add ringbuffer data structure --- kernel/util/ringbuffer.c | 85 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 kernel/util/ringbuffer.c diff --git a/kernel/util/ringbuffer.c b/kernel/util/ringbuffer.c new file mode 100644 index 0000000..27ff0f7 --- /dev/null +++ b/kernel/util/ringbuffer.c @@ -0,0 +1,85 @@ +#ifndef RINGBUFFER_C +#define RINGBUFFER_C + +#include +#include "../alloc.c" + +/* + * Data layout: ↓head + * [ 4, undef, undef, 1, 2, 3 ] (1 is first added etc.) + * So enqueue adds after 4 and dequeue removes 1. + */ +struct ringbuffer { + int head; + int size; + void** buffer; + int buffer_n; +}; + +void rbfr_clear(struct ringbuffer* this) { + this->size = 0; + this->head = 0; +} + +struct ringbuffer* rbfr_create(const int capacity) { + struct ringbuffer* const this = alloc(sizeof (struct ringbuffer)); + + this->buffer = alloc(capacity * sizeof (void*)); + this->buffer_n = capacity; + rbfr_clear(this); + + return this; +} + +void rbfr_destroy(struct ringbuffer* this) { + free(this->buffer); + free(this); +} + +int rbfr_size(const struct ringbuffer* this) { + return this->size; +} + +int rbfr_capacity(const struct ringbuffer* this) { + return this->buffer_n; +} + +void rbfr_enqueue(struct ringbuffer* this, void* element) { + if (this->buffer_n == 0) { + return; + } + + int index = this->head + this->size; + if (index >= this->buffer_n) { + index -= this->buffer_n; + } + this->buffer[index] = element; + if (this->size < this->buffer_n) { + this->size++; + } else { + this->head++; + } + return; +} + +bool rbfr_peek(const struct ringbuffer* this, void** element) { + if (this->size == 0) { + return false; + } + *element = this->buffer[this->head]; + return true; +} + +bool rbfr_dequeue(struct ringbuffer* this, void** element) { + if (!rbfr_peek(this, element)) { + return false; + } + this->size--; + this->head++; + if (this->head >= this->buffer_n) { + this->head = 0; + } + return true; +} + +#endif // RINGBUFFER_C