Compare commits

..

No commits in common. "4c6348a0ee41267d3abee541685ecfb7888f6d38" and "b99b8ed7517fd92b47288538b0ada2699a9955e7" have entirely different histories.

3 changed files with 21 additions and 137 deletions

View file

@ -2,7 +2,6 @@
#include <assert.h> #include <assert.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#define DEFAUL_REGION_SIZE 1048576 /* 8 * 1024 * 1024 = 8MB */ #define DEFAUL_REGION_SIZE 1048576 /* 8 * 1024 * 1024 = 8MB */
@ -12,67 +11,19 @@ Region *new_region(size_t capacity) {
} }
Region *region = malloc(capacity + sizeof(Region)); Region *region = malloc(capacity + sizeof(Region));
assert(region != NULL); assert(region != NULL);
*region = (Region){.next = NULL, .capacity = capacity, .cursor = 0}; *region = (Region){.next = NULL,
.capacity = capacity,
// Zero initialise memory .cursor = 0};
memset(region->data, 0, capacity);
return region; return region;
} }
Arena *arena_init(Arena *parent, size_t capacity) { Arena arena_init(size_t capacity) {
Region *region = new_region(capacity); Region *region = new_region(capacity);
Arena arena = {.begin = region, .end = region};
if (parent != NULL) {
// Allocate new arena in parent to reduce likelyhood of loss
Arena *current_arena = arena_alloc(parent, sizeof(Arena));
*current_arena = (Arena){.parent = parent,
.begin = region,
.end = region,
.child = NULL,
.sibling = NULL};
// if parent has no children this arena is now it's child
if (parent->child == NULL) {
parent->child = current_arena;
return current_arena;
}
// Push the arena onto the first childs sibling list
current_arena->sibling = parent->child;
parent->child = current_arena;
return current_arena;
}
// Create root of arena tree
Arena *arena = malloc(sizeof(Arena));
*arena = (Arena){.parent = NULL,
.begin = region,
.end = region,
.child = NULL,
.sibling = NULL};
return arena; return arena;
} }
void arena_deinit(Arena *arena) { void arena_deinit(Arena *arena) {
if (arena == NULL) {
return;
}
// Recursively deinit children
while (arena->child != NULL) {
Arena *current_child = arena->child;
arena->child = current_child->sibling;
arena_deinit(current_child);
}
// Run deinit tasks before freeing data
while (arena->deinit_task_top != NULL) {
assert(arena->deinit_task_top->func_ptr != NULL);
arena->deinit_task_top->func_ptr(arena->deinit_task_top->func_param);
arena->deinit_task_top = arena->deinit_task_top->next;
}
// actually free the data
assert(arena->begin != NULL && arena->end != NULL); assert(arena->begin != NULL && arena->end != NULL);
Region *region = arena->begin; Region *region = arena->begin;
while (region != NULL) { while (region != NULL) {
@ -80,34 +31,10 @@ void arena_deinit(Arena *arena) {
free(region); free(region);
region = next_region; region = next_region;
} }
*arena = (Arena){.begin = NULL, .end = NULL};
arena->begin = NULL;
arena->end = NULL;
// If we're the tree root free us from malloc
if (arena->parent == NULL) {
free(arena);
return;
}
// Now that we have no descendants tell our parent and siblings of our death
if (arena->parent->child == arena) {
arena->parent->child = arena->sibling;
return;
}
Arena *previous_sibling = arena->parent->child;
while (previous_sibling != NULL && previous_sibling->sibling != arena) {
previous_sibling = previous_sibling->sibling;
}
if (previous_sibling != NULL) {
previous_sibling->sibling = arena->sibling;
}
} }
void *arena_alloc(Arena *arena, size_t size) { void *arena_alloc(Arena *arena, size_t size) {
// TODO: only align when needed
size = (size + 7) & ~7; // align size increase to multiple of 8
Region *region = arena->end; Region *region = arena->end;
assert(region != NULL); assert(region != NULL);
@ -119,16 +46,10 @@ void *arena_alloc(Arena *arena, size_t size) {
void *result = &region->data[region->cursor]; void *result = &region->data[region->cursor];
region->cursor += size; region->cursor += size;
// TODO: only align when needed
size = (size + 7) & ~7; // align size increase to multiple of 8
return result; return result;
} }
void arena_run_on_deinit_push(Arena *arena, ArenaDeinitTask task) { // void *arena_clear(Arena *arena) {
ArenaDeinitTask *job = arena_alloc(arena, sizeof(ArenaDeinitTask)); // arena->size = 0;
*job = task; // return arena->data;
// }
ArenaDeinitTask *next_job = arena->deinit_task_top;
arena->deinit_task_top = job;
job->next = next_job;
}

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
typedef struct Region_s Region; typedef struct Region_s Region;
struct Region_s { struct Region_s {
@ -10,28 +11,13 @@ struct Region_s {
unsigned char data[]; unsigned char data[];
}; };
typedef struct ArenaDeinitTask_s ArenaDeinitTask; typedef struct {
struct ArenaDeinitTask_s {
void *func_param;
void (*func_ptr)(void *);
ArenaDeinitTask *next;
};
ArenaDeinitTask ArenaDeinitTask_default = {NULL};
typedef struct Arena_s Arena;
struct Arena_s {
Arena *parent;
Arena *child;
Arena *sibling;
Region *begin; Region *begin;
Region *end; Region *end;
ArenaDeinitTask *deinit_task_top; } Arena;
};
Arena *arena_init(Arena *parent, size_t capacity); Arena arena_init(size_t capacity);
void arena_deinit(Arena *arena); void arena_deinit(Arena *arena);
void arena_run_on_deinit_push(Arena *arena, ArenaDeinitTask task);
void *arena_alloc(Arena *arena, size_t size); void *arena_alloc(Arena *arena, size_t size);
//void *arena_clear(Arena *arena); //void *arena_clear(Arena *arena);

View file

@ -10,37 +10,14 @@
#include "arena_allocator.h" #include "arena_allocator.h"
/* /*int main(int argc, char *argv[]) {
int main(int argc, char *argv[]) { Arena global_arena = arena_init(0);
// arena allocation test
printf("Allocation test\n");
Arena *global_arena = arena_init(NULL, 0);
for (int i = 0; i <= 1048576+100; i++) { for (int i = 0; i <= 1048576+100; i++) {
int *number = arena_alloc(global_arena, sizeof(int)); int *number = arena_alloc(&global_arena, sizeof(int));
*number = 42; *number = 42;
} }
arena_deinit(&global_arena);
// arena children test }*/
printf("children test\n");
Arena *child_arena = arena_init(global_arena, 0);
Arena *sibling_arena = arena_init(global_arena, 0);
Arena *grandchild_arena = arena_init(child_arena, 0);
Arena *greatgrandchild_arena = arena_init(grandchild_arena, 0);
Arena *greatgrandchildsibling_arena = arena_init(grandchild_arena, 0);
Arena *greatgrandchildsiblingsibling_arena = arena_init(grandchild_arena, 0);
Arena *greategreatgrandchild_arena =
arena_init(greatgrandchildsibling_arena, 0);
Arena *greatsiblinggreatgrandchild_arena =
arena_init(greatgrandchildsiblingsibling_arena, 0);
printf("deinit tests\n");
arena_deinit(greatgrandchild_arena);
arena_deinit(global_arena);
printf("tests complete\n");
}
*/
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
wn_window window = {0}; wn_window window = {0};