Skip to content

Commit

Permalink
Add a threadsafe example implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
phillipjohnston committed Mar 1, 2021
1 parent b567e5b commit ccc886a
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 0 deletions.
166 changes: 166 additions & 0 deletions examples/c/circular_buffer/circular_buffer_no_modulo_threadsafe.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <assert.h>

#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;
}
9 changes: 9 additions & 0 deletions examples/c/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down

0 comments on commit ccc886a

Please sign in to comment.