From ccc886a92551d1f55f5b9d65f07968361e77a25d Mon Sep 17 00:00:00 2001 From: Phillip Johnston Date: Mon, 1 Mar 2021 15:44:34 -0800 Subject: [PATCH] Add a threadsafe example implementation. --- .../circular_buffer_no_modulo_threadsafe.c | 166 ++++++++++++++++++ examples/c/meson.build | 9 + 2 files changed, 175 insertions(+) create mode 100644 examples/c/circular_buffer/circular_buffer_no_modulo_threadsafe.c diff --git a/examples/c/circular_buffer/circular_buffer_no_modulo_threadsafe.c b/examples/c/circular_buffer/circular_buffer_no_modulo_threadsafe.c new file mode 100644 index 0000000..484662a --- /dev/null +++ b/examples/c/circular_buffer/circular_buffer_no_modulo_threadsafe.c @@ -0,0 +1,166 @@ +#include +#include +#include +#include + +#include "circular_buffer.h" + +// The definition of our circular buffer structure is hidden from the user +struct circular_buf_t { + uint8_t * buffer; + size_t head; + size_t tail; + size_t max; //of the buffer +}; + +#pragma mark - Private Functions - + +static void advance_pointer(cbuf_handle_t cbuf) +{ + assert(cbuf); + + if(circular_buf_full(cbuf)) + { + if(++(cbuf->tail) == cbuf->max) + { + cbuf->tail = 0; + } + } + + if(++(cbuf->head) == cbuf->max) + { + cbuf->head = 0; + } +} + +static void retreat_pointer(cbuf_handle_t cbuf) +{ + assert(cbuf); + + if(++(cbuf->tail) == cbuf->max) + { + cbuf->tail = 0; + } +} + +#pragma mark - APIs - + +cbuf_handle_t circular_buf_init(uint8_t* buffer, size_t size) +{ + assert(buffer && size); + + cbuf_handle_t cbuf = malloc(sizeof(circular_buf_t)); + assert(cbuf); + + cbuf->buffer = buffer; + cbuf->max = size; + circular_buf_reset(cbuf); + + assert(circular_buf_empty(cbuf)); + + return cbuf; +} + +void circular_buf_free(cbuf_handle_t cbuf) +{ + assert(cbuf); + free(cbuf); +} + +void circular_buf_reset(cbuf_handle_t cbuf) +{ + assert(cbuf); + + cbuf->head = 0; + cbuf->tail = 0; +} + +size_t circular_buf_size(cbuf_handle_t cbuf) +{ + assert(cbuf); + + size_t size = cbuf->max; + + if(!circular_buf_full(cbuf)) + { + if(cbuf->head >= cbuf->tail) + { + size = (cbuf->head - cbuf->tail); + } + else + { + size = (cbuf->max + cbuf->head - cbuf->tail); + } + + } + + return size; +} + +size_t circular_buf_capacity(cbuf_handle_t cbuf) +{ + assert(cbuf); + + return cbuf->max; +} + +void circular_buf_put(cbuf_handle_t cbuf, uint8_t data) +{ + assert(cbuf && cbuf->buffer); + + cbuf->buffer[cbuf->head] = data; + + advance_pointer(cbuf); +} + +int circular_buf_put2(cbuf_handle_t cbuf, uint8_t data) +{ + int r = -1; + + assert(cbuf && cbuf->buffer); + + if(!circular_buf_full(cbuf)) + { + cbuf->buffer[cbuf->head] = data; + advance_pointer(cbuf); + r = 0; + } + + return r; +} + +int circular_buf_get(cbuf_handle_t cbuf, uint8_t * data) +{ + assert(cbuf && data && cbuf->buffer); + + int r = -1; + + if(!circular_buf_empty(cbuf)) + { + *data = cbuf->buffer[cbuf->tail]; + retreat_pointer(cbuf); + + r = 0; + } + + return r; +} + +bool circular_buf_empty(cbuf_handle_t cbuf) +{ + assert(cbuf); + + return (!circular_buf_full(cbuf) && (cbuf->head == cbuf->tail)); +} + +bool circular_buf_full(circular_buf_t* cbuf) +{ + // We need to handle the wraparound case + size_t head = cbuf->head + 1; + if(head == cbuf->max) + { + head = 0; + } + + return head == cbuf->tail; +} diff --git a/examples/c/meson.build b/examples/c/meson.build index 15e7f01..8dc3f46 100644 --- a/examples/c/meson.build +++ b/examples/c/meson.build @@ -26,6 +26,15 @@ executable('circular_buffer_no_modulo', c_args: '-DCOMPILE_AS_EXAMPLE' ) +executable('circular_buffer_no_modulo_threadsafe', + [ + 'circular_buffer_test.c', + 'circular_buffer/circular_buffer_no_modulo_threadsafe.c' + ], + include_directories: include_directories('circular_buffer'), + c_args: '-DCOMPILE_AS_EXAMPLE' +) + executable('malloc_aligned', 'malloc_aligned.c', c_args: '-DCOMPILE_AS_EXAMPLE',