aboutsummaryrefslogtreecommitdiff
path: root/src/std/scoped_allocator.c
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-02-27 22:26:35 +0100
committerdec05eba <dec05eba@protonmail.com>2020-07-25 14:36:46 +0200
commit76d85a10f6cda93eba29dad5372e8160af7289c8 (patch)
treecfec3043ec45a5e83494ec109e87c239dad6cc47 /src/std/scoped_allocator.c
parent8201cd9f40897cf6b8e6973b28a8661108702ab1 (diff)
Use multiple threads to parse
Diffstat (limited to 'src/std/scoped_allocator.c')
-rw-r--r--src/std/scoped_allocator.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/std/scoped_allocator.c b/src/std/scoped_allocator.c
new file mode 100644
index 0000000..d53edad
--- /dev/null
+++ b/src/std/scoped_allocator.c
@@ -0,0 +1,102 @@
+#include "../../include/std/scoped_allocator.h"
+#include "../../include/std/alloc.h"
+#include <assert.h>
+
+#define ALLOC_NODE_SIZE 4096
+
+int scoped_allocator_node_init(ScopedAllocatorNode *self) {
+ self->data = NULL;
+ self->size = 0;
+ self->next = NULL;
+ return am_malloc(ALLOC_NODE_SIZE, (void**)&self->data);
+}
+
+void scoped_allocator_node_deinit(ScopedAllocatorNode *self) {
+ am_free(self->data);
+ self->data = NULL;
+ self->size = 0;
+ if(self->next) {
+ scoped_allocator_node_deinit(self->next);
+ am_free(self->next);
+ self->next = NULL;
+ }
+}
+
+int scoped_allocator_init(ScopedAllocator *self) {
+ return_if_error(scoped_allocator_node_init(&self->head));
+ self->current = &self->head;
+ return buffer_init(&self->buffers, NULL);
+}
+
+static void buffer_deinit(Buffer *self) {
+ am_free(self->data);
+ self->data = NULL;
+ self->size = 0;
+ self->capacity = 0;
+}
+
+void scoped_allocator_deinit(ScopedAllocator *self) {
+ Buffer *buffer;
+ Buffer *buffer_end;
+
+ scoped_allocator_node_deinit(&self->head);
+ self->current = NULL;
+ buffer = (Buffer*)self->buffers.data;
+ buffer_end = buffer + self->buffers.size / sizeof(Buffer);
+ while(buffer != buffer_end) {
+ buffer_deinit(buffer);
+ ++buffer;
+ }
+ buffer_deinit(&self->buffers);
+}
+
+static CHECK_RESULT int scoped_allocator_ensure_capacity_for(ScopedAllocator *self, usize size) {
+ void *new_node;
+ new_node = NULL;
+
+ if(self->current->size + size > ALLOC_NODE_SIZE) {
+ return_if_error(am_malloc(sizeof(ScopedAllocatorNode), &new_node));
+ cleanup_if_error(scoped_allocator_node_init(new_node));
+ self->current->next = new_node;
+ self->current = new_node;
+ }
+ return ALLOC_OK;
+
+ cleanup:
+ if(new_node)
+ am_free(new_node);
+ return ALLOC_FAIL;
+}
+
+static void* align_ptr_ceil(void *ptr, uintptr_t alignment) {
+ uintptr_t ptrval;
+ ptrval = (uintptr_t)ptr;
+ return (void*)((ptrval + alignment + 1) & ~(alignment - 1));
+}
+
+static usize align_ptr_ceil_offset(void *ptr, uintptr_t alignment) {
+ return (uintptr_t)align_ptr_ceil(ptr, alignment) - (uintptr_t)ptr;
+}
+
+int scoped_allocator_alloc(ScopedAllocator *self, usize size, void **mem) {
+ ScopedAllocatorNode *current;
+ usize alloc_size;
+ assert(self->current);
+ assert(size <= ALLOC_NODE_SIZE);
+ current = self->current;
+
+ alloc_size = size + align_ptr_ceil_offset(self->current->data + self->current->size, 16);
+ return_if_error(scoped_allocator_ensure_capacity_for(self, alloc_size));
+ /* Reallocated (new node created) */
+ if(self->current != current) {
+ *mem = self->current->data;
+ } else {
+ *mem = align_ptr_ceil(self->current->data + self->current->size, 16);
+ }
+ self->current->size = size;
+ return 0;
+}
+
+int scoped_allocator_add_buffer(ScopedAllocator *self, Buffer *buffer) {
+ return buffer_append(&self->buffers, buffer, sizeof(Buffer));
+} \ No newline at end of file