#include "base.cpp" struct Arena_Block { Arena_Block *next; Arena_Block *prev; size_t cap; size_t 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; }; 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; } } if (!block) { block = (Arena_Block *)allocate_size(arena->block_allocator, sizeof(Arena_Block) + min_size + default_alignment, false); block->cap = min_size + default_alignment; } 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; return (void *)result; } static Arena_Block_Based make_arena_block_based(Allocator *allocator) { Arena_Block_Based result = {}; result.block_allocator = allocator; result.alignment = default_alignment; result.allocate = (Allocator::Allocate *)block_arena_push_size; result.deallocate = (Allocator::Deallocate *)deallocate_stub; return result; } struct CRT_Heap : Allocator {}; static void *crt_allocate(Allocator *allocator, size_t size) { return malloc(size); } static void crt_deallocate(Allocator *allocator, void *p) { return free(p); } static CRT_Heap make_crt_heap() { CRT_Heap result = {}; result.allocate = crt_allocate; 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); }