Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Circular buffer improvements #37

Merged
merged 3 commits into from
Mar 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/c/circular_buffer/circular_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ static void advance_pointer(cbuf_handle_t cbuf)
{
assert(cbuf);

if(cbuf->full)
if(circular_buf_full(cbuf))
{
cbuf->tail = (cbuf->tail + 1) % cbuf->max;
}
Expand Down Expand Up @@ -78,7 +78,7 @@ size_t circular_buf_size(cbuf_handle_t cbuf)

size_t size = cbuf->max;

if(!cbuf->full)
if(!circular_buf_full(cbuf))
{
if(cbuf->head >= cbuf->tail)
{
Expand Down Expand Up @@ -147,7 +147,7 @@ bool circular_buf_empty(cbuf_handle_t cbuf)
{
assert(cbuf);

return (!cbuf->full && (cbuf->head == cbuf->tail));
return (!circular_buf_full(cbuf) && (cbuf->head == cbuf->tail));
}

bool circular_buf_full(cbuf_handle_t cbuf)
Expand Down
167 changes: 167 additions & 0 deletions examples/c/circular_buffer/circular_buffer_no_modulo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#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
bool full;
};

#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;
}

// We mark full because we will advance tail on the next time around
cbuf->full = (cbuf->head == cbuf->tail);
}

static void retreat_pointer(cbuf_handle_t cbuf)
{
assert(cbuf);

cbuf->full = false;
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;
cbuf->full = false;
}

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(cbuf_handle_t cbuf)
{
assert(cbuf);

return cbuf->full;
}
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;
}
18 changes: 18 additions & 0 deletions examples/c/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ executable('circular_buffer',
c_args: '-DCOMPILE_AS_EXAMPLE'
)

executable('circular_buffer_no_modulo',
[
'circular_buffer_test.c',
'circular_buffer/circular_buffer_no_modulo.c'
],
include_directories: include_directories('circular_buffer'),
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