Musa-STL-Cpp/lib/Base/Base_Thread_Context.cpp

101 lines
3.8 KiB
C++

// See Context_Base in jai, and TCTX in raddebugger:
struct Push_Allocator_Label {
string old_label;
Push_Allocator_Label(string new_label) {
old_label = thread_context()->allocator_label;
thread_context()->allocator_label = copy_string_untracked(new_label);
}
~Push_Allocator_Label() {
string_free_untracked(thread_context()->allocator_label);
thread_context()->allocator_label = old_label;
}
};
internal void Bootstrap_Main_Thread_Context () {
Timed_Block_Print_No_Context("Bootstrap_Main_Thread_Context");
// 0. Setup general allocator
default_allocator_initialize_tracking();
// 1. Setup arena free list
// #note: the arena free list is disabled because I'm not convinced it's a good idea.
// It would allow us to cache arenas to load address space very quickly (much faster than calling VirtualAlloc), but
// it adds complexity and makes it difficult to know when you're doing something stupid, because memory is still writeable
// and readable after it's "freed" with `release_arena`. So for prototyping purposes, we just release the whole arena.
// arena_free_list = (Arena_Free_List*)default_allocator_new(sizeof(Arena_Free_List), 64, true); // permanent allocation.
// memset(arena_free_list, 0, sizeof(Arena_Free_List));
// initialize_arena_free_list(default_allocator());
// 1b. Setup arena in-use list:
initialize_arenas_in_use_list();
// 2. #NewContext Setup thread local context
ExpandableArena* arena_ex = bootstrap_expandable_arena(Arena_Reserve::Size_64M, "Main Thread Arena");
thread_local_context = New<Thread_Context>(allocator(arena_ex));
push_allocator_label("Main Thread Initialization");
thread_local_context->temp = bootstrap_expandable_arena(Arena_Reserve::Size_2M, "Main Thread Temp");
thread_local_context->arena = arena_ex;
thread_local_context->allocator = allocator(arena_ex);
thread_local_context->thread_idx = 0;
thread_local_context->thread_name = "Main Thread";
// #TODO (Low priority) This is redundant! There should just be one string_builder!
thread_local_context->log_builder = new_string_builder(Arena_Reserve::Size_64M, "Main Thread Log Builder");
thread_local_context->string_builder = new_string_builder(Arena_Reserve::Size_2M, "Main Thread String Builder");
thread_local_context->error_arena = bootstrap_arena(Arena_Reserve::Size_64M, "Main Thread Error Arena");
default_logger_initialize();
thread_local_context->logger = {default_logger_proc, &default_logger};
}
struct Push_Arena {
Thread_Context* context;
Allocator original_allocator;
Push_Arena(ExpandableArena* arena_ex) {
Assert(is_valid(arena_ex));
context = thread_context();
Assert(context != nullptr);
original_allocator = context->allocator;
context->allocator = allocator(arena_ex);
}
Push_Arena(Arena* arena) {
Assert(is_valid(arena));
context = thread_context();
Assert(context != nullptr);
original_allocator = context->allocator;
context->allocator = allocator(arena);
}
Push_Arena(FixedArena* arena) {
Assert(is_valid(arena));
context = thread_context();
Assert(context != nullptr);
original_allocator = context->allocator;
context->allocator = allocator(arena);
}
~Push_Arena() {
context->allocator = original_allocator;
}
};
force_inline void set_thread_context (Thread_Context* new_context) {
thread_local_context = new_context;
}
// #Note: Both functions will free next arenas, we only worry about keeping memory in the first arena (typically 64MB).
void temp_reset_keeping_memory() {
Thread_Context* context = thread_context();
arena_reset(context->temp, false);
}
void temp_reset() { // alias: reset_temporary_storage.
Thread_Context* context = thread_context();
arena_reset(context->temp, true);
}