Added: Arena allocator improvements
This commit is contained in:
parent
bcebc14b5a
commit
3866404505
81
src/arena.c
81
src/arena.c
|
@ -1,40 +1,93 @@
|
||||||
|
|
||||||
internal Arena *
|
internal Arena *
|
||||||
arena_initialize(u64 size)
|
arena_initialize(u64 size, b8 growable)
|
||||||
{
|
{
|
||||||
Arena *result = 0;
|
Arena *result = 0;
|
||||||
|
void *backing_buffer = platform_memory_reserve(size);
|
||||||
void *backing_buffer = malloc(size);
|
|
||||||
|
|
||||||
if (backing_buffer != NULL)
|
if (backing_buffer != NULL)
|
||||||
{
|
{
|
||||||
result = (Arena*) backing_buffer;
|
platform_memory_commit(backing_buffer, ARENA_INITIAL_COMMIT_SIZE);
|
||||||
|
|
||||||
result->buffer = backing_buffer;
|
result = (Arena*) backing_buffer;
|
||||||
result->offset = sizeof(Arena);
|
result->backing_buffer = (u64*) backing_buffer;
|
||||||
result->size = sizeof(Arena) + size;
|
result->current = result;
|
||||||
|
result->prev = 0;
|
||||||
|
|
||||||
|
// rhjr: immutable arena header
|
||||||
|
result->base_pos =
|
||||||
|
memory_align(sizeof(Arena), ARENA_DEFAULT_ALIGNMENT);
|
||||||
|
result->offset = result->base_pos;
|
||||||
|
|
||||||
|
result->growable = growable;
|
||||||
|
result->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rhjr: arenas should be instantiated early on in the programs lifetime, that
|
||||||
|
// is why this assertion will also be used in production.
|
||||||
|
ASSERT(result != 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Arena *
|
||||||
|
arena_initialize_default()
|
||||||
|
{
|
||||||
|
Arena *result = arena_initialize(ARENA_DEFAULT_RESERVE_SIZE, 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void *
|
internal void *
|
||||||
arena_allocate(Arena *arena, u64 size)
|
arena_allocate(Arena *arena, u64 size)
|
||||||
{
|
{
|
||||||
void *result = 0;
|
Arena *current = arena->current;
|
||||||
|
u64 pos_cur = current->base_pos + current->offset;
|
||||||
|
u64 pos_mem = memory_align(pos_cur, ARENA_DEFAULT_ALIGNMENT);
|
||||||
|
u64 pos_new = pos_mem + size;
|
||||||
|
|
||||||
if (arena->offset + size <= arena->size)
|
if (current->size < pos_new && current->growable)
|
||||||
{
|
{
|
||||||
result = (void*)((u64) arena->buffer + (u64) arena->offset);
|
Arena *new_memory_bock;
|
||||||
arena->offset += size;
|
|
||||||
|
|
||||||
memset(result, 0, size);
|
if (size > ARENA_DEFAULT_RESERVE_SIZE)
|
||||||
|
{
|
||||||
|
// rhjr: TODO add support for allocations larger then a single page, in a
|
||||||
|
// single allocation call.
|
||||||
|
ASSERT(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_memory_bock = arena_initialize_default();
|
||||||
|
|
||||||
|
if (new_memory_bock)
|
||||||
|
{
|
||||||
|
stack_push(arena->current, new_memory_bock, prev);
|
||||||
|
|
||||||
|
current = new_memory_bock;
|
||||||
|
|
||||||
|
pos_mem =
|
||||||
|
memory_align(current->offset, ARENA_DEFAULT_ALIGNMENT);
|
||||||
|
pos_new = current->offset + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memory = (void*)((u64) current->backing_buffer + pos_mem);
|
||||||
|
arena->offset = pos_new;
|
||||||
|
|
||||||
|
platform_memory_commit(memory, size);
|
||||||
|
memset(memory, 0, size);
|
||||||
|
|
||||||
|
return memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
arena_release(Arena *arena)
|
arena_release(Arena *arena)
|
||||||
{
|
{
|
||||||
arena->offset = 0;
|
for (Arena *node = arena->current, *prev = 0; node != 0; node = prev)
|
||||||
|
{
|
||||||
|
prev = node->prev;
|
||||||
|
platform_memory_release(node, node->size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
25
src/arena.h
25
src/arena.h
|
@ -1,19 +1,30 @@
|
||||||
#ifndef ARENA_H
|
#ifndef ARENA_H
|
||||||
#define ARENA_H
|
#define ARENA_H
|
||||||
|
|
||||||
|
#define ARENA_INITIAL_COMMIT_SIZE sizeof(struct Arena)
|
||||||
|
#define ARENA_DEFAULT_ALIGNMENT 0
|
||||||
|
|
||||||
|
#ifndef ARENA_DEFAULT_RESERVE_SIZE
|
||||||
|
# define ARENA_DEFAULT_RESERVE_SIZE KB(4)
|
||||||
|
#endif // ARENA_DEFAULT_RESERVE_SIZE
|
||||||
|
|
||||||
typedef struct Arena Arena;
|
typedef struct Arena Arena;
|
||||||
struct Arena {
|
struct Arena {
|
||||||
u64 *buffer;
|
struct Arena *current;
|
||||||
|
struct Arena *prev;
|
||||||
|
u64 *backing_buffer;
|
||||||
|
u64 base_pos;
|
||||||
u64 offset;
|
u64 offset;
|
||||||
u64 size;
|
u64 size;
|
||||||
|
b8 growable;
|
||||||
};
|
};
|
||||||
|
|
||||||
internal Arena * arena_initialize(u64 size);
|
//= rhjr: arenas
|
||||||
|
|
||||||
|
internal Arena * arena_initialize(u64 size, b8 growable);
|
||||||
|
internal Arena * arena_initialize_default();
|
||||||
|
|
||||||
internal void * arena_allocate(Arena *arena, u64 size);
|
internal void * arena_allocate(Arena *arena, u64 size);
|
||||||
internal void arena_release(Arena *arena);
|
|
||||||
|
|
||||||
//= rhjr: arena helpers
|
|
||||||
|
|
||||||
#define arena_push_array(arena, type, count) \
|
#define arena_push_array(arena, type, count) \
|
||||||
(type*) arena_allocate((arena), sizeof(type) * (count))
|
(type*) arena_allocate((arena), sizeof(type) * (count))
|
||||||
|
@ -21,8 +32,12 @@ internal void arena_release(Arena *arena);
|
||||||
#define arena_push(arena, type) \
|
#define arena_push(arena, type) \
|
||||||
(type*) arena_allocate((arena), sizeof(type))
|
(type*) arena_allocate((arena), sizeof(type))
|
||||||
|
|
||||||
|
internal void arena_release(Arena *arena);
|
||||||
|
|
||||||
//= rhjr: memory helpers
|
//= rhjr: memory helpers
|
||||||
|
|
||||||
|
#define memory_align(x, b) ((b != 0) ? (((x) + (b) - 1) & (~(b - 1))) : (x))
|
||||||
|
|
||||||
#define memory_zero(s,z) memset((s), 0, (z))
|
#define memory_zero(s,z) memset((s), 0, (z))
|
||||||
#define memory_zero_struct(s) memory_zero((s), sizeof(*(s)))
|
#define memory_zero_struct(s) memory_zero((s), sizeof(*(s)))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user