+/*
+ 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;
+}
+