// API in Arena.h #include global b64 arena_tables_initialized = false; global std::mutex arena_table_mutex; global s32 arenas_in_flight_count[6]; global Array arena_free_table[6]; #if BUILD_DEBUG global Array arenas_in_flight[6]; #endif void initialize_arena_table () { for (s32 i = 0; i < 6; i += 1) { arena_free_table[i].allocator = GPAllocator(); arenas_in_flight[i].allocator = GPAllocator(); array_reserve(arena_free_table[i], 64); array_reserve(arenas_in_flight[i], 64); } arena_tables_initialized = true; } Arena* next_arena (Arena_Reserve reserve_size) { Arena* arena; std::lock_guard lock(arena_table_mutex); s64 reserve_index = (s64)reserve_size; arenas_in_flight_count[reserve_index] += 1; if (!arena_free_table[reserve_index].count) { arena = bootstrap_arena(reserve_size, ARENA_DEFAULT_COMMIT_PAGE_COUNT); } else { arena = pop(arena_free_table[reserve_index]); } #if ARENA_DEBUG array_add(arenas_in_flight[reserve_index], arena); #endif Assert(arena != nullptr); return arena; } void release_arena (Arena* arena, bool delete_extra_pages) { std::lock_guard lock(arena_table_mutex); s64 reserve_index = (s64)arena->reserve_size; #if ARENA_DEBUG array_unordered_remove_by_value(arenas_in_flight[reserve_index], arena, 1); #endif arena_reset_keeping_memory(arena); if (delete_extra_pages) { free_pages_down_to(arena, arena->initial_commit_page_count); } array_add(arena_free_table[reserve_index], arena); arenas_in_flight_count[reserve_index] -= 1; // #TODO: Garbage collection if we have >> 64 in a particular table for a while. // if (arena_free_table[reserve_index].count > 64) { // release some arenas if required // arena_delete(...) } }