diff options
Diffstat (limited to 'cached.c')
-rw-r--r-- | cached.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/cached.c b/cached.c new file mode 100644 index 0000000..8174cda --- /dev/null +++ b/cached.c @@ -0,0 +1,73 @@ +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include "cached.h" + +static size_t object_size; +static size_t max_cached; +static size_t num_cached; +static void **cache; + +int +ca_setup(size_t osize, size_t csize) +{ + /* TODO allow osize == 0 following malloc? */ + if (osize == 0 || csize == 0) { + return -1; + } + + cache = calloc(csize, sizeof(*cache)); + if (cache == NULL) { + return -2; + } + + object_size = osize; + max_cached = csize; + num_cached = 0; + + return 0; +} + +void * +ca_alloc(void) +{ + assert(cache != NULL); + + if (num_cached > 0) { + void *object = cache[--num_cached]; + return object; + } + + return calloc(1, object_size); +} + +void +ca_free(void *object) +{ + assert(cache != NULL); + + if (object == NULL) { + /* free(3) also does nothing for NULL */ + return; + } + + if (num_cached < max_cached) { + cache[num_cached++] = object; + /* memset here to catch dangling references */ + memset(object, 0, object_size); + return; + } + + free(object); +} + +void +ca_cleanup(void) +{ + for (size_t i = 0; i < num_cached; i++) { + free(cache[i]); + } + free(cache); + cache = NULL; +} |