Initial version of arena allocator.
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *arena_alloc(Arena *a, size_t size) {
|
// out of memory in arena, handle by doubling arena size;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user