]> git.mdlowis.com Git - projs/alib.git/commitdiff
added headers for reference counting and arena memory management master
authorMichael D. Lowis <mike.lowis@gentex.com>
Fri, 29 Jun 2018 17:49:31 +0000 (13:49 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Fri, 29 Jun 2018 17:49:31 +0000 (13:49 -0400)
src/arena.h [new file with mode: 0644]
src/ref.h [new file with mode: 0644]

diff --git a/src/arena.h b/src/arena.h
new file mode 100644 (file)
index 0000000..969aa26
--- /dev/null
@@ -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 <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;
+}
+
diff --git a/src/ref.h b/src/ref.h
new file mode 100644 (file)
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 <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;
+}