aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriamcheeseman <[email protected]>2026-05-29 22:28:43 -0400
committeriamcheeseman <[email protected]>2026-05-29 22:28:43 -0400
commit648504907c9f62adc72628ae73a8c668ec1276c8 (patch)
treed95ba176f4677581e2b3971e8cea4179ba908023
parent840b5c151fcd207e904fb2a6d3bb3fd658ef6209 (diff)
Generic arena allocator
Also replaces the temp allocator behind the scenes
-rw-r--r--editor/editor.c6
-rw-r--r--teensy/teensy_mem.c86
-rw-r--r--teensy/teensy_mem.h28
3 files changed, 106 insertions, 14 deletions
diff --git a/editor/editor.c b/editor/editor.c
index 53d24a3..efbee8b 100644
--- a/editor/editor.c
+++ b/editor/editor.c
@@ -78,10 +78,10 @@ int editor_main(void)
while (ty_is_game_running()) {
int ticks = ty_tick();
- for (int i = 0; i < ticks; i++)
+ for (int i = 0; i < ticks; i++) {
tick();
-
- ty_free_temp_allocs();
+ ty_clear_temp_allocs();
+ }
}
for (int i = 0; i < CHAR_MAX; i++) {
diff --git a/teensy/teensy_mem.c b/teensy/teensy_mem.c
index d32cabf..cea24cb 100644
--- a/teensy/teensy_mem.c
+++ b/teensy/teensy_mem.c
@@ -1,26 +1,92 @@
#include "teensy_mem.h"
+#include <string.h>
+
#include "teensy_common.h"
#include "teensy_list.h"
-#define TEMP_ALLOC_ARENA_SIZE (1024*1024)
+#define ARENA_DEFAULT_HUNK_SIZE (1<<16) // ~65KB
-uint8_t temp_arena[TEMP_ALLOC_ARENA_SIZE];
-uint8_t *next_temp_alloc = temp_arena;
+Arena temp_arena;
-void *ty_talloc(size_t size)
+static
+Arena_Hunk *create_new_hunk(size_t hunk_size)
+{
+ Arena_Hunk *hunk = ty_new(Arena_Hunk);
+ memset(hunk, 0, sizeof(Arena_Hunk));
+
+ hunk->start = ty_alloc(hunk_size);
+ hunk->end = hunk->start + hunk_size;
+ hunk->head = hunk->start;
+
+ return hunk;
+}
+
+void *ty_arena_alloc(Arena *arena, size_t size)
{
- if (next_temp_alloc > temp_arena + TEMP_ALLOC_ARENA_SIZE)
- ty_log_fatal(TY_ERR_MEM, "bump up the temp alloc arena size");
+ Arena_Hunk *hunk = arena->hunks;
+ while (hunk) {
+ if (hunk->head + size < hunk->end)
+ break;
+ hunk = hunk->next;
+ }
+
+ if (!hunk) {
+ // I like these lines
+ arena->hunk_size = arena->hunk_size
+ ? arena->hunk_size : ARENA_DEFAULT_HUNK_SIZE;
+
+ hunk = create_new_hunk(arena->hunk_size);
+ hunk = create_new_hunk(arena->hunk_size);
+ hunk->next = arena->hunks;
+ arena->hunks = hunk;
+ }
+
+ void *ptr = hunk->head;
+ memset(ptr, 0, size);
+
+ hunk->head += size;
+ arena->alloced_size += size;
- void *ptr = next_temp_alloc;
- next_temp_alloc += size;
return ptr;
}
-void ty_free_temp_allocs(void)
+void ty_arena_clear(Arena *arena)
+{
+ Arena_Hunk *hunk = arena->hunks;
+ while (hunk) {
+ hunk->head = hunk->start;
+ hunk = hunk->next;
+ }
+
+ arena->alloced_size = 0;
+}
+
+void ty_arena_free(Arena *arena)
+{
+ Arena_Hunk *hunk = arena->hunks;
+ while (hunk) {
+ Arena_Hunk *next = hunk->next;
+
+ ty_free(hunk->start);
+ ty_free(hunk);
+
+ hunk = next;
+ }
+
+ arena->hunks = NULL;
+ arena->alloced_size = 0;
+}
+
+void *ty_talloc(size_t size)
+{
+ return ty_arena_alloc(&temp_arena, size);
+}
+
+void ty_clear_temp_allocs(void)
{
- next_temp_alloc = temp_arena;
+ ty_log_debug("%zu/%zu", temp_arena.alloced_size, temp_arena.hunk_size);
+ ty_arena_clear(&temp_arena);
}
void *ty_alloc(size_t size)
diff --git a/teensy/teensy_mem.h b/teensy/teensy_mem.h
index 133869f..b4cdc62 100644
--- a/teensy/teensy_mem.h
+++ b/teensy/teensy_mem.h
@@ -1,11 +1,37 @@
#ifndef TEENSY_MEM_H_
#define TEENSY_MEM_H_
+#include <stdint.h>
#include <stdlib.h>
#define ty_new(T) (ty_alloc(sizeof(T)))
-void ty_free_temp_allocs(void);
+// A specific section of memory allocated for an arena.
+typedef struct Arena_Hunk Arena_Hunk;
+struct Arena_Hunk {
+ Arena_Hunk *next;
+ uint8_t *start;
+ uint8_t *end;
+ uint8_t *head;
+};
+
+// Memory arena. It allows the user of this API to allocate lots of memory and
+// free it all at once. Arenas do not support reallocation.
+typedef struct {
+ Arena_Hunk *hunks;
+ size_t hunk_size;
+ size_t alloced_size;
+} Arena;
+
+// Makes an allocation with the speicified arena.
+void *ty_arena_alloc(Arena *arena, size_t size);
+// Frees all allocations made with this arena.
+void ty_arena_clear(Arena *arena);
+// Frees the arena itself. Do NOT call to free allocations made with the arena.
+// Use `ty_arena_clear()` for that.
+void ty_arena_free(Arena *arena);
+
+void ty_clear_temp_allocs(void);
// Temp allocation. Freed at the end of every frame. Do NOT realloc.
void *ty_talloc(size_t size);