diff --git a/.gitignore b/.gitignore index 29d36c8..a43b0c7 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ linked-list mandelbrot mandelbrot.bmp threads +structs +circular-buffer diff --git a/Makefile b/Makefile index fb79bd5..f62d539 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CFLAGS=-std=c99 -Wall -g -O2 INDENTOPTS=-kr --no-tabs --braces-on-func-def-line --indent-level2 -TARGETS=approximate-pi linked-list mandelbrot mandelbrot.bmp threads +TARGETS=approximate-pi linked-list mandelbrot mandelbrot.bmp threads circular-buffer structs .PHONY: all all: $(TARGETS) diff --git a/circular-buffer.c b/circular-buffer.c new file mode 100644 index 0000000..0a5abd7 --- /dev/null +++ b/circular-buffer.c @@ -0,0 +1,172 @@ +/* Circular buffer, using a counter to distinguish full from empty buffer. */ + +#include +#include +#include + +#include + +#define DEBUG 0 +#define debug_printf(fmt, ...) \ + do { if (DEBUG) fprintf(stderr, fmt, __VA_ARGS__); } while (0) + +#define CB_SIZE 42 + +/* Types */ + +struct elem { + int foo; +}; +typedef struct elem elem_t; + +struct cb { + int count; + int size; + int start; + int end; + + elem_t * elems; +}; +typedef struct cb cb_t; + + +/* Helpers */ + +void dienomem() { + fprintf(stderr, "ERROR: No memory?!\n"); + exit(1); +} + +/* Operations */ + +void cb_init(cb_t * cb, int size) { + cb->count = 0; + cb->size = size; + + cb->start = 0; + + cb->elems = malloc(sizeof(elem_t)*size); + if (!cb->elems) + dienomem(); +} + +void cb_free(cb_t * cb) { + free(cb->elems); +} + +bool cb_is_full(cb_t * cb) { + return (cb->count == cb->size); +} + +bool cb_is_empty(cb_t * cb) { + return (cb->count == 0); +} + +int cb_count(cb_t * cb) { + return cb->count; +} + +void cb_write(cb_t * cb, elem_t * elem) { + int end = (cb->start + cb->count) % cb->size; + cb->elems[end] = *elem; + + if (cb_is_full(cb)) + /* We have just overwritten the first element of the buffer, + * therefore move the start. */ + cb->start = (cb->start + 1) % cb->size; + else + cb->count++; +} + +bool cb_read(cb_t * cb, elem_t * elem) { + if (!cb_is_empty(cb)) { + *elem = cb->elems[cb->start]; + cb->start = (cb->start + 1) % cb->size; + cb->count--; + return true; + } else { + return false; + } +} + +/* Test it. */ + +int main(int argc, char *argv[]) { + /* Initialize empty CB_SIZE-element circular buffer. */ + cb_t *test_cb = malloc(sizeof(cb_t)); + if (!test_cb) + dienomem(); + cb_init(test_cb, CB_SIZE); + + /* Should be empty. */ + assert(cb_is_empty(test_cb) == true); + assert(cb_is_full(test_cb) == false); + + /* Add one element. */ + elem_t *one = malloc(sizeof(elem_t)); + one->foo = 23; + cb_write(test_cb, one); + free(one); + assert(cb_is_empty(test_cb) == false); + + /* Read the one element. */ + elem_t *oneback = malloc(sizeof(elem_t)); + cb_read(test_cb, oneback); + assert(oneback->foo == 23); + free(oneback); + assert(cb_is_empty(test_cb) == true); + + /* Fill the buffer. */ + elem_t *e = malloc(sizeof(elem_t)); + for (int i = 1; i <= CB_SIZE; i++) { + e->foo = i; + cb_write(test_cb, e); + } + assert(cb_is_empty(test_cb) == false); + assert(cb_is_full(test_cb) == true); + assert(cb_count(test_cb) == CB_SIZE); + + /* Add another element. */ + e->foo = CB_SIZE + 1; + cb_write(test_cb, e); + assert(cb_is_empty(test_cb) == false); + assert(cb_is_full(test_cb) == true); + assert(cb_count(test_cb) == CB_SIZE); + + /* Read all elements and check their values. */ + for (int i = 2; i <= CB_SIZE + 1; i++) { + bool rc = cb_read(test_cb, e); + assert(rc == true); + debug_printf("e->foo == %d\n", e->foo); + assert(e->foo == i); + } + assert(cb_is_empty(test_cb) == true); + + /* Should not be possible to read a value now. */ + bool rc = cb_read(test_cb, e); + assert(rc == false); + assert(cb_is_empty(test_cb) == true); + assert(cb_count(test_cb) == 0); + + /* Fill the buffer - twice. */ + for (int i = 1; i <= CB_SIZE * 2; i++) { + e->foo = i; + cb_write(test_cb, e); + } + assert(cb_is_empty(test_cb) == false); + assert(cb_is_full(test_cb) == true); + assert(cb_count(test_cb) == CB_SIZE); + + /* Read all elements and check their values. */ + for (int i = CB_SIZE + 1; i <= CB_SIZE * 2; i++) { + bool rc = cb_read(test_cb, e); + assert(rc == true); + assert(e->foo == i); + } + assert(cb_is_empty(test_cb) == true); + + /* Free buffer etc. */ + free(e); + cb_free(test_cb); + free(test_cb); +} diff --git a/structs.c b/structs.c new file mode 100644 index 0000000..dfc0013 --- /dev/null +++ b/structs.c @@ -0,0 +1,19 @@ +#include + +struct test { + int foo; +}; +typedef struct test test_t; + +int main(int argc, char * argv[]) { + test_t a = { 23 }; + test_t b = { 42 }; + + a = b; + assert(a.foo == 42); + assert(b.foo == 42); + + a.foo = 69; + assert(a.foo == 69); + assert(b.foo == 42); +}