Initial version of arena allocator.

This commit is contained in:
2025-02-08 08:47:44 +02:00
parent 4502339527
commit acd7eabb5c
+67 -6
View File
@@ -5,7 +5,9 @@ Heavily inspired and designed from:
* https://github.com/gingerBill/gb/ * https://github.com/gingerBill/gb/
This is a single header file that contains: This is a single header file that contains:
- allocators - Arena allocator
- Stack allocator (todo)
- Pool allocator (todo)
References: References:
https://www.gingerbill.org/series/memory-allocation-strategies/ https://www.gingerbill.org/series/memory-allocation-strategies/
@@ -14,7 +16,7 @@ A implementation of the above with changes were I felt I needed them.
To use this library, do this in *one* C: To use this library, do this in *one* C:
#define JH_MEM_IMPLEMENTATION #define JH_MEM_IMPLEMENTATION
#include "jh_io.h" #include "jh_mem.h"
NOTE: NOTE:
This is intended to be used with the jh.h header. This is intended to be used with the jh.h header.
@@ -29,6 +31,10 @@ And will require jh.h as it uses the typedefs defined in that file.
#define DEFAULT_ALIGNMENT (2*sizeof(void *)) #define DEFAULT_ALIGNMENT (2*sizeof(void *))
#endif #endif
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
typedef struct Arena Arena; typedef struct Arena Arena;
struct Arena { struct Arena {
u8 *data; u8 *data;
@@ -37,11 +43,23 @@ struct Arena {
usize curr_offset; usize curr_offset;
}; };
bool is_power_of_two(uptr x); u8 is_power_of_two(uptr x);
uptr align_forward(uptr ptr, usize align); uptr align_forward(uptr ptr, usize align);
void *arena_alloc_align(Arena *a, usize size, usize align); void *arena_alloc_align(Arena *a, usize size, usize align);
void *arena_alloc(Arena *a, usize size); void *arena_alloc(Arena *a, usize size);
// Free the allocated arena
void arena_free(&Arena);
// "clears" the arena by placing the offset to the beggining.
// Allowing reuse of arena without having to free/alloc.
void arena_reset(&Arena);
// Initializes an arena instance.
// On malloc fail it will return the arena with data as NULL
// REQUIRED to arena.data after used
Arena arena_new(usize arena_init_size);
// -------------------------------------- // --------------------------------------
// -------------------------------------- // --------------------------------------
// implementation Below // implementation Below
@@ -52,7 +70,7 @@ void *arena_alloc(Arena *a, usize size);
// Arena Functions Start // Arena Functions Start
// -------------------------------------- // --------------------------------------
bool is_power_of_two(uintptr_t x) { u8 is_power_of_two(uintptr_t x) {
return (x & (x-1)) == 0; return (x & (x-1)) == 0;
} }
@@ -75,17 +93,60 @@ uptr align_forward(uptr ptr, usize align) {
} }
void *arena_alloc_align(Arena *a, usize size, usize align) { void *arena_alloc_align(Arena *a, usize size, usize align) {
// get the pointer
uptr current_ptr = (uptr)a->data + (uptr)a->curr_offset; uptr current_ptr = (uptr)a->data + (uptr)a->curr_offset;
// align the offset if needed
uptr offset = align_forward(current_ptr, align); uptr offset = align_forward(current_ptr, align);
// Change to relative offset // Change the pointer to relative offset number
offset -= (uptr)a->data; offset -= (uptr)a->data;
if (offset+size <= a->data_len) {
void *ptr = &a->buf[offset];
a->prev_offset = offset;
a->curr_offset = offset+size;
// Zero new memory
memset(ptr, 0, size);
return ptr;
}
// out of memory in arena, handle by doubling arena size;
return NULL;
} }
void *arena_alloc(Arena *a, size_t size) { void *arena_alloc(Arena *a, usize size) {
return arena_alloc_align(a, size, DEFAULT_ALIGNMENT); return arena_alloc_align(a, size, DEFAULT_ALIGNMENT);
} }
void arena_reset(Arena *arena) {
arena->curr_offset = 0;
arena->prev_offset = 0;
}
void arena_free(Arena* arena) {
if (arena != NULL && arena->data != NULL) {
free(arena->data);
arena->data = NULL;
}
}
Arena arena_new(usize arena_init_size) {
Arena arena = {0};
arena.data = (u8 *)malloc(arena_init_size);
if(arena.data == NULL) {
return arena;
}
arena.data_len = arena_init_size;
arena.curr_offset = 0;
arena.prev_offset = 0;
return arena;
}
// -------------------------------------- // --------------------------------------
// Arena Functions END // Arena Functions END
// -------------------------------------- // --------------------------------------