about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorLyla B <lyla@entropy.garden>2020-08-14 23:37:13 -0400
committerLyla B <lyla@entropy.garden>2020-08-14 23:37:13 -0400
commit4fd963c85035852b7b4b0407de5a89afc1874fbf (patch)
treea20a3f036a502db6b40f88654235f24ceb85eeff
downloadarena-master.tar.gz
Initial commit. HEAD master
-rw-r--r--README.md17
-rw-r--r--arena.c56
-rw-r--r--arena.h15
3 files changed, 88 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ac03e6f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,17 @@
+# arena
+Minimal arena allocator for C.
+
+## Installation
+The **arena.c** and **arena.h** files can be dropped into an existing C project
+and compiled it along it.
+
+## Usage
+- `arena_t* arena_create_sized(size_t size);`: Create an arena with size `size`
+
+- `arena_t* arena_create(void);`: Create an arena with a compile-time specified
+  page size (4096 by default)
+
+- `void* arena_malloc(arena_t* arena, size_t size);`: Allocate `size` bytes inside
+  the arena
+
+- `void arena_destroy(arena_t* arena);`: Destroy the arena
diff --git a/arena.c b/arena.c
new file mode 100644
index 0000000..3e1a57c
--- /dev/null
+++ b/arena.c
@@ -0,0 +1,56 @@
+#include "arena.h"
+#include <stdlib.h>
+#define PAGE_SIZE 4096
+enum {
+	ARENA_SUCCESS = 0,
+	ARENA_EXPAND,
+	ARENA_FAILURE,
+}
+int arena_errno;
+arena_t* arena_create_sized(size_t size){
+	arena_t* arena = (arena_t*) calloc(1, sizeof(arena_t*));
+	if (!arena) {
+		arena_errno = ARENA_FAILURE;
+		return 0;
+	}
+	arena->memory = (uint8_t*) calloc(1, size);
+	arena->size = size;
+	if (!arena->memory) {
+		free(arena);
+		arena_errno = ARENA_FAILURE;
+		return 0;
+	}
+	arena_errno = ARENA_SUCCESS;
+	return arena;
+}
+arena_t* arena_create() {
+	return arena_create_sized(PAGE_SIZE);
+}
+void* arena_malloc(arena_t* arena, size_t size) {
+	arena_t* head = arena;
+	arena_t* tail;
+	do {
+		if ((arena->size - arena->fill) > size) {
+			arena->fill += size;
+			// NOTE: do not overwrite ARENA_EXPAND code
+			if (arena_errno != ARENA_EXPAND) arena_errno = ARENA_SUCCESS;
+			return arena->memory + (arena->fill - size);
+		}
+	} while ((arena = arena->next) != 0);
+	tail = arena_create();
+	if (tail == 0) {
+		// NOTE: `arena_errno` is already set from `arena_create`
+		return 0;
+	}
+	arena_errno = ARENA_EXPAND;
+	return arena_malloc(tail, size);
+}
+void arena_destroy(arena_t* arena) {
+	arena_t* tail = arena;
+	do {
+		free(tail->memory);
+		free(tail);
+		tail = tail->next;
+	} while (tail != 0);
+	arena_errno = ARENA_SUCCESS;
+}
diff --git a/arena.h b/arena.h
new file mode 100644
index 0000000..4594070
--- /dev/null
+++ b/arena.h
@@ -0,0 +1,15 @@
+#ifndef ARENA_H
+#define ARENA_H
+#include <stdint.h>
+#include <stddef.h>
+typedef struct arena {
+	uint8_t* memory;
+	size_t size;
+	size_t fill;
+	struct arena* next;
+} arena_t;
+arena_t* arena_create_sized(size_t size);
+arena_t* arena_create(void);
+void* arena_malloc(arena_t* arena, size_t size);
+void arena_destroy(arena_t* arena);
+#endif