Working on simplifying the allocation scheme
This commit is contained in:
138
core_arena.cpp
138
core_arena.cpp
@@ -1,67 +1,97 @@
|
||||
#include "base.cpp"
|
||||
constexpr size_t ARENA_BLOCK_SIZE = mib(1);
|
||||
constexpr size_t ARENA_ALIGNMENT = 8;
|
||||
|
||||
struct Arena_Block {
|
||||
Arena_Block *next;
|
||||
Arena_Block *prev;
|
||||
size_t cap;
|
||||
size_t len;
|
||||
struct Scratch_Arena : Allocator {
|
||||
int cap, len;
|
||||
uint8_t memory[];
|
||||
};
|
||||
|
||||
constexpr size_t default_block_size = mib(1);
|
||||
struct Arena_Block_Based : Allocator {
|
||||
Arena_Block *first;
|
||||
Arena_Block *last;
|
||||
Arena_Block *first_free;
|
||||
Allocator *block_allocator;
|
||||
size_t alignment;
|
||||
struct Scratch_Scope {
|
||||
Scratch_Arena *arena;
|
||||
int pos;
|
||||
Scratch_Scope(Scratch_Arena *arena) { this->arena = arena; this->pos = arena->len; }
|
||||
~Scratch_Scope() { this->arena->len = this->pos; }
|
||||
};
|
||||
|
||||
static void arena_add_block(Arena_Block_Based *arena, size_t min_size) {
|
||||
Arena_Block *block = 0;
|
||||
for (Arena_Block *it = arena->first_free; it; it = it->next) {
|
||||
if (it->cap > min_size) {
|
||||
block = it;
|
||||
DLL_STACK_REMOVE(arena->first_free, it);
|
||||
break;
|
||||
}
|
||||
static void *scratch_arena_push_size(Scratch_Arena *arena, size_t size) {
|
||||
size_t generous_size = size + ARENA_ALIGNMENT;
|
||||
if (arena->len + generous_size > arena->cap) {
|
||||
assert(size < arena->cap);
|
||||
assert_message(0, "Scratch arena is too small, failed to handle a request, capacity: %d, occupied: %d, allocation: %d", generous_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!block) {
|
||||
block = (Arena_Block *)allocate_size(arena->block_allocator, sizeof(Arena_Block) + min_size + default_alignment, false);
|
||||
block->cap = min_size + default_alignment;
|
||||
}
|
||||
size_t aligned_fill = align_up((size_t)arena->memory + arena->len, ARENA_ALIGNMENT) - (size_t)arena->memory;
|
||||
assert(((int64_t)aligned_fill - (int64_t)arena->len) >= 0);
|
||||
assert(((int64_t)aligned_fill - (int64_t)arena->len) <= ARENA_ALIGNMENT);
|
||||
arena->len = aligned_fill;
|
||||
|
||||
block->len = 0;
|
||||
block->next = 0;
|
||||
block->prev = 0;
|
||||
DLL_QUEUE_ADD(arena->first, arena->last, block);
|
||||
}
|
||||
|
||||
static void *block_arena_push_size(Arena_Block_Based *arena, size_t size) {
|
||||
size_t generous_size = size + arena->alignment;
|
||||
if (!arena->last || (arena->last->len + generous_size > arena->last->cap)) {
|
||||
assert(arena->block_allocator);
|
||||
size_t block_size = max(default_block_size, generous_size);
|
||||
arena_add_block(arena, block_size);
|
||||
}
|
||||
|
||||
Arena_Block *L = arena->last;
|
||||
size_t adjusted_len = align_up((size_t)L->memory + L->len, arena->alignment) - (size_t)L->memory;
|
||||
assert(((int64_t)adjusted_len - (int64_t)L->len) > 0);
|
||||
assert(((int64_t)adjusted_len - (int64_t)L->len) <= arena->alignment);
|
||||
L->len = adjusted_len;
|
||||
|
||||
uint8_t *result = L->memory + L->len;
|
||||
L->len += size;
|
||||
uint8_t *result = arena->memory + arena->len;
|
||||
arena->len += size;
|
||||
return (void *)result;
|
||||
}
|
||||
|
||||
static Arena_Block_Based make_arena_block_based(Allocator *allocator) {
|
||||
Arena_Block_Based result = {};
|
||||
static Scratch_Arena *allocate_scratch_arena(Allocator *allocator, size_t size_without_members) {
|
||||
Scratch_Arena *scratch = (Scratch_Arena *)allocate_size(allocator, size_without_members + sizeof(Scratch_Arena), false);
|
||||
scratch->cap = size_without_members;
|
||||
scratch->len = 0;
|
||||
scratch->allocate = (Allocator::Allocate *)scratch_arena_push_size;
|
||||
scratch->deallocate = deallocate_stub;
|
||||
return scratch;
|
||||
}
|
||||
|
||||
struct Push_Arena_Block {
|
||||
Push_Arena_Block *next;
|
||||
uint8_t memory[];
|
||||
};
|
||||
|
||||
struct Push_Arena : Allocator {
|
||||
Allocator *block_allocator;
|
||||
Push_Arena_Block *blocks;
|
||||
size_t allocated_block_count;
|
||||
size_t block_fill;
|
||||
size_t wasted_memory;
|
||||
};
|
||||
|
||||
static void push_arena_add_block(Push_Arena *arena) {
|
||||
Push_Arena_Block *block = (Push_Arena_Block *)allocate_size(arena->block_allocator, sizeof(Push_Arena_Block) + ARENA_BLOCK_SIZE, false);
|
||||
memory_zero(block, sizeof(Push_Arena_Block));
|
||||
SLL_STACK_ADD(arena->blocks, block);
|
||||
if (arena->allocated_block_count) arena->wasted_memory += ARENA_BLOCK_SIZE - arena->block_fill;
|
||||
arena->allocated_block_count += 1;
|
||||
arena->block_fill = 0;
|
||||
}
|
||||
|
||||
static void push_arena_deallocate(Push_Arena *arena) {
|
||||
for(Push_Arena_Block *it = arena->blocks; it; it = it->next) {
|
||||
deallocate(arena->block_allocator, it);
|
||||
}
|
||||
memory_zero(arena, sizeof(*arena));
|
||||
}
|
||||
|
||||
static void *push_arena_push_size(Push_Arena *arena, size_t size) {
|
||||
assert(arena->block_allocator);
|
||||
assert(size < ARENA_BLOCK_SIZE / 2);
|
||||
size_t generous_size = size + ARENA_ALIGNMENT;
|
||||
if (arena->blocks == 0 || (arena->block_fill + generous_size > ARENA_BLOCK_SIZE)) {
|
||||
push_arena_add_block(arena);
|
||||
}
|
||||
|
||||
Push_Arena_Block *L = arena->blocks;
|
||||
size_t aligned_fill = align_up((size_t)L->memory + arena->block_fill, ARENA_ALIGNMENT) - (size_t)L->memory;
|
||||
assert(((int64_t)aligned_fill - (int64_t)arena->block_fill) >= 0);
|
||||
assert(((int64_t)aligned_fill - (int64_t)arena->block_fill) <= ARENA_ALIGNMENT);
|
||||
arena->block_fill = aligned_fill;
|
||||
|
||||
uint8_t *result = L->memory + arena->block_fill;
|
||||
arena->block_fill += size;
|
||||
return (void *)result;
|
||||
}
|
||||
|
||||
static Push_Arena make_push_arena(Allocator *allocator) {
|
||||
Push_Arena result = {};
|
||||
result.block_allocator = allocator;
|
||||
result.alignment = default_alignment;
|
||||
result.allocate = (Allocator::Allocate *)block_arena_push_size;
|
||||
result.allocate = (Allocator::Allocate *)push_arena_push_size;
|
||||
result.deallocate = (Allocator::Deallocate *)deallocate_stub;
|
||||
return result;
|
||||
}
|
||||
@@ -75,9 +105,3 @@ static CRT_Heap make_crt_heap() {
|
||||
result.deallocate = crt_deallocate;
|
||||
return result;
|
||||
}
|
||||
|
||||
int main() {
|
||||
CRT_Heap heap = make_crt_heap();
|
||||
Arena_Block_Based arena = make_arena_block_based(&heap);
|
||||
void *result = allocate_size(&arena, 32);
|
||||
}
|
||||
Reference in New Issue
Block a user