From: Michael D. Lowis Date: Fri, 29 Jun 2018 17:49:31 +0000 (-0400) Subject: added headers for reference counting and arena memory management X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=HEAD;p=projs%2Falib.git added headers for reference counting and arena memory management --- diff --git a/src/arena.h b/src/arena.h new file mode 100644 index 0000000..969aa26 --- /dev/null +++ b/src/arena.h @@ -0,0 +1,67 @@ +/* + Simple implementation of arena-based memory management. + + Copyright 2018, Michael D. Lowis + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA + OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. +*/ +#include + +typedef struct arena_page_t { + struct arena_page_t* next; + void** pos; + void** end; + void* buf[]; +} arena_page_t; + +typedef struct { + arena_page_t* pages; +} arena_t; + +void* aalloc(arena_t* a, size_t sz) { + if (a->pages && (a->pages->end - a->pages->pos) >= sz) { + void* block = a->pages->pos; + a->pages->pos += sz / sizeof(void*); + a->pages->pos += (sz % sizeof(void*) ? 1 : 0); + return block; + } else { + size_t pgsize = sysconf(_SC_PAGE_SIZE), + size_t blksz = ((sz / pgsize + 1) << 1); + arena_page_t* page = malloc(blksz); + page->pos = &(page->buf); + page->end = ((void*)page + blksz); + page->next = a->pages; + a->pages = page; + return aalloc(a, sz); + } +} + +static arena_t* acreate(void) { + arena_t temp_arena = { 0 }; + arena_t* arena = aalloc(&temp_arena, sizeof(arena_t)); + arena->pages = temp_arena.pages; + return arena; +} + +static arena_t* adestroy(arena_t* a) { + arena_page_t* page = a->pages; + while (page) { + arena_page_t dead = page; + page = page->next; + free(page); + } + return NULL; +} + diff --git a/src/ref.h b/src/ref.h new file mode 100644 index 0000000..07fc11e --- /dev/null +++ b/src/ref.h @@ -0,0 +1,65 @@ +/* + Simple reference counting routines for ANSI C. + + Copyright 2018, Michael D. Lowis + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA + OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. +*/ +#include + +typedef struct obj_t { + void (*dtor)(void*); + size_t refs; + uint8_t data[]; +} obj_t; + +void* refcreate(size_t sz, void (*dtor)(void*)) { + obj_t* obj = malloc(sizeof(obj_t) + sz); + if (obj) { + obj->dtor = dtor; + obj->refs = 1u; + } else { +#ifndef NO_ABORT + perror("refcreate() failed :"); + abort(); +#else + return NULL; +#endif + } + return obj->data; +} + +void* refalloc(size_t sz) { + return refcreate(sz, 0); +} + +void* refretain(void* obj) { + ((obj_t*)obj - 1u)->refs++; + return obj; +} + +void* refrelease(void* obj) { + obj_t* rcobj = ((obj_t*)obj - 1u); + rcobj->refs--; + if (!rcobj->refs) { + if (rcobj->dtor) rcobj->dtor(obj); + free(rcobj); + } + return NULL; +} + +size_t refcount(void* obj) { + return ((obj_t*)obj - 1u)->refs; +}