--- /dev/null
+/*
+ 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 <stdlib.h>
+
+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;
+}
+
--- /dev/null
+/*
+ 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 <stdlib.h>
+
+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;
+}