diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..22f1bb2 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,60 @@ +############# README ############# README ############# README ############ +# Option to choose between shared or static library +# Pass this as an argument as follows when configuring the project: +# `cmake -S . -B build +# then build it with either `Release` or `Debug` option: +# `cmake --build build --config Release` +############ /README ############ /README ############ /README ############ + +cmake_minimum_required(VERSION 3.20) + +project(musa-explorer-cpp) + +# Use C++11 +SET (CMAKE_CXX_STANDARD 11) +SET (CMAKE_VERBOSE_MAKEFILE ON) + +if (MSVC) + # Suppress warning: C++ exception handler used, but unwind semantics are not enabled. + add_compile_options(/wd4530) +endif() + +SET (EXE_NAME "mexplore_v2") + +SET (SRC_FILES + lib/third_party/dear-imgui/imgui.cpp + lib/third_party/dear-imgui/imgui_widgets.cpp + lib/third_party/dear-imgui/imgui_draw.cpp + lib/third_party/dear-imgui/imgui_tables.cpp + lib/third_party/dear-imgui/imgui_impl_dx11.cpp + lib/third_party/dear-imgui/imgui_impl_win32.cpp + + exe_main.cpp +) + +SET (INCLUDE_DIRS + ${PROJECT_SOURCE_DIR}/src + ${PROJECT_SOURCE_DIR}/lib + ${PROJECT_SOURCE_DIR}/lib/third_party +) + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + SET (LINK_LIB_DIRS + ) +elseif(CMAKE_BUILD_TYPE STREQUAL "Release") + SET (LINK_LIB_DIRS + ) +endif() + +add_executable(${EXE_NAME} ${SRC_FILES}) +target_include_directories(${EXE_NAME} PRIVATE ${INCLUDE_DIRS}) +target_link_libraries(${EXE_NAME} PRIVATE ${LINK_LIBS_DIRS}) + +message(STATUS "Build type: $") + +add_custom_command(TARGET ${EXE_NAME} POST_BUILD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND ${CMAKE_COMMAND} -E echo "Running post-build script..." + COMMAND cmd.exe /c "${CMAKE_SOURCE_DIR}/copy_files.cmd" $ + COMMENT "Running custom post-build script." +) diff --git a/README.md b/README.md index 102b539..ebd8fc8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,49 @@ -build either with `build.cmd Debug` or `build.cmd Release` -Run `build_imgui_lib.cmd` to build imgui dependency -Both scripts must be run in x64 Native Tools Command Prompt for VS 20xx. +# Build Overview -You can also build with `jai build.jai - build_exe` or `jai build.jai - build_exe release` +- #TODO: Explain build configuration: library, exe +- Why do we use CMake (even though I hate it)? (because it's industry standard?) +- Plans to use a metaprogram to modify code for certain reasons (e.g. getting stack traces) + +## Configuration +This project uses CMake to configure and build. Currently only Win32 is supported. +``` +cmake -S . -B build +``` +## Build +To build in debug mode: +``` +cmake --build build --config Debug +``` +To build in release mode: +``` +cmake --build build --config Release +``` + +## Roadmap for Supporting Other platforms + +- Linux +- MacOS +- Android +- iOS + +# APIs + +## Base Layer + +### Thread-local Context + +## OS Platform Layer + +## Debug Tooling + + + +# Explorer Application Notes + +## File Enumeration + +## Sorting + +## Searching Algorithms + +## Multithreading \ No newline at end of file diff --git a/build.cmd b/build.cmd deleted file mode 100644 index cc8d037..0000000 --- a/build.cmd +++ /dev/null @@ -1,56 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -if "%~1"=="" ( - echo Usage: build.cmd [Debug^|Release] - exit /b 1 -) - -set CONFIG=%~1 - -if /I "%CONFIG%"=="Debug" ( - set CFLAGS=/MDd /Od /Zi /DDEBUG /DEBUG -diagnostics:caret -diagnostics:column -D_CRT_SECURE_NO_WARNINGS -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING -D_CRT_NONSTDC_NO_DEPRECATE -D_USE_MATH_DEFINES - set LIB_PATH=bin - set IMGUI_LIB_PATH=bin\Debug\dear-imgui.lib -) else if /I "%CONFIG%"=="Release" ( - set CFLAGS=/MD /O2 /DNDEBUG - set LIB_PATH=bin - set IMGUI_LIB_PATH=bin\Release\dear-imgui.lib -) else ( - echo Invalid configuration: %CONFIG% - echo Usage: build.cmd [Debug^|Release] - exit /b 1 -) - -set OBJDIR=obj - -if not exist "%LIB_PATH%" mkdir "%LIB_PATH%" -if not exist obj mkdir obj - -set LIB_NAME=musa - -set SRC_FILES=^ - exe_main.cpp - -set INCLUDE_DIRS=^ - /Isrc ^ - /Ilib ^ - /Ilib\api ^ - /Ithird_party - -set LINK_LIBS=^ - %IMGUI_LIB_PATH% - -rem NOTE: it defaults to C++11, so /std:c++11 is redundant -rem SHARED LIBRARY: - rem echo Building DLL (%CONFIG%) - rem cl /nologo /EHsc /DWIN32 /wd4530 %CFLAGS% %INCLUDE_DIRS% %SRC_FILES% /LD /Fe%LIB_PATH%\%LIB_NAME%.dll /Fo%OBJDIR%\ /link %LINK_LIBS% -echo Building EXE (%CONFIG%)... -cl /nologo /EHsc /DWIN32 /wd4530 %CFLAGS% %INCLUDE_DIRS% %SRC_FILES% /link /MACHINE:AMD64 %LINK_LIBS% /OUT:%LIB_PATH%\%LIB_NAME%.exe - -rem cleanup... -rd /s /q "%OBJDIR%" - -rem echo Running post-build script... -rem nothing to do (for now). -endlocal diff --git a/build.jai b/build.jai deleted file mode 100644 index 0c0b9ad..0000000 --- a/build.jai +++ /dev/null @@ -1,150 +0,0 @@ -// Some notes: -// To generate the intermediate to see how many lines are being compiled, in x64 Native Tools Command Prompt for VS2022 or whatever -// cl /P /EP exe_main.cpp -// tokei exe_main.i -VERSION :: "0.2"; - -#run,stallable build_cpp_project(); - -LIB_BASE_NAME :: "musa-lib"; -EXE_BASE_NAME :: "musa"; - -LIB_SOURCE_FILENAMES :: string.["lib_main.cpp"]; -EXE_SOURCE_FILENAMES :: string.["exe_main.cpp"]; - -INCLUDE_DIRS :: string.[ - "src", - "lib", - "lib/api", - "third_party" -]; - - -build_cpp_project :: () { - start := seconds_since_init(); - - set_build_options_dc(.{do_output=false}); - options := get_build_options(); - args := options.compile_time_command_line; - - compile_debug := true; - if array_find(args, "release") { compile_debug = false; } - build_lib := array_find(args, "build_lib"); - build_exe := array_find(args, "build_exe"); - - generate_meta_file(compile_debug); - if build_lib build_cpp_lib(compile_debug); - if build_exe build_cpp_exe(compile_debug); - - print("\nFull build time: % seconds\n\n", FF(seconds_since_init() - start, 3)); -} - -build_cpp_exe :: (compile_debug: bool) { - extra: [..]string; - if os_target == { - case .WINDOWS; - array_add(*extra, "-D_CRT_SECURE_NO_WARNINGS", "-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING", "-D_CRT_NONSTDC_NO_DEPRECATE"); - array_add(*extra, "-D_USE_MATH_DEFINES"); // , "-D_WIN32_WINNT=0x0A00", "/utf-8" - - array_add(*extra, "/MT"); // Static - The default - - for INCLUDE_DIRS array_add(*extra, tprint("/I%", it)); - case; assert(false, "Other OSes not supported yet!"); - } - - exe_path := tprint("bin/%", EXE_BASE_NAME); - make_directory_if_it_does_not_exist("bin"); - LINK_LIBS: []string; - if (compile_debug) { LINK_LIBS = .["bin/Debug/dear-imgui.lib"]; } - else { LINK_LIBS = .["bin/Release/dear-imgui.lib"]; } - - success := build_cpp_executable(exe_path, ..EXE_SOURCE_FILENAMES, debug=compile_debug, extra=extra, library_files=LINK_LIBS); - print("\nbuild_cpp_executable, success: %\n", success); -} - -build_cpp_lib :: (compile_debug: bool) -> bool { - lib_path := tprint("bin/Debug/%", LIB_BASE_NAME); - if !compile_debug { - lib_path = tprint("bin/Release/%", LIB_BASE_NAME); - } - lib_directory := path_strip_filename(lib_path); - make_directory_if_it_does_not_exist(lib_directory, recursive = true); - print("Output lib_path: %\n\n", lib_path); - - extra: [..]string; - if os_target == { - case .WINDOWS; - array_add(*extra, "-D_CRT_SECURE_NO_WARNINGS", "-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING", "-D_CRT_NONSTDC_NO_DEPRECATE"); - array_add(*extra, "-D_USE_MATH_DEFINES"); // , "-D_WIN32_WINNT=0x0A00", "/utf-8" - - // array_add(*extra, "/MD"); // Dynamic - array_add(*extra, "/MT"); // Static - The default - - for INCLUDE_DIRS array_add(*extra, tprint("/I%", it)); - case .LINUX; - array_add(*extra, "-fPIC"); - array_add(*extra, tprint("-I/%/%", #filepath, "JIIM_Library")); - for INCLUDE_DIRS array_add(*extra, tprint("-I/%/%", #filepath, it)); - case; assert(false, "Other OSes not supported yet!"); - } - - success := build_cpp_static_lib(lib_path, ..LIB_SOURCE_FILENAMES, debug=compile_debug, extra=extra); - print("\nbuild_cpp_static_lib, success: %\n", success); - return success; -} - -META_GENERATED_HEADER_FILE_PATH :: "lib/meta_generated.h"; - -cpu_target: CPU_Tag = .X64; -os_target: Operating_System_Tag = .WINDOWS; - -generate_meta_file :: (debug: bool) { - sb: String_Builder; - append(*sb, "#pragma once\n\n"); - print_to_builder(*sb, "const char* MUSA_LIB_VERSION = \"%\";\n", VERSION); - print_to_builder(*sb, "#define BUILD_DEBUG %\n", cast(s32)debug); - - print_to_builder(*sb, "#define OS_WINDOWS %\n", ifx os_target == .WINDOWS then 1 else 0); - print_to_builder(*sb, "#define OS_LINUX %\n", ifx os_target == .LINUX then 1 else 0); - print_to_builder(*sb, "#define OS_MACOS %\n", ifx os_target == .MACOS then 1 else 0); - print_to_builder(*sb, "#define OS_ANDROID %\n", ifx os_target == .ANDROID then 1 else 0); - print_to_builder(*sb, "#define OS_IOS %\n", ifx os_target == .IOS then 1 else 0); - - print_to_builder(*sb, "#define ARCH_CPU_X64 %\n", ifx cpu_target == .X64 then 1 else 0); - print_to_builder(*sb, "#define ARCH_CPU_ARM64 %\n", ifx cpu_target == .ARM64 then 1 else 0); - - os_is_unix := os_target == .MACOS || os_target == .LINUX || os_target == .IOS || os_target == .ANDROID; - print_to_builder(*sb, "#define OS_IS_UNIX %\n", ifx os_is_unix then 1 else 0); - - print_to_builder(*sb, "#define COMPILER_MSVC %\n", ifx os_target == .WINDOWS then 1 else 0); - print_to_builder(*sb, "#define COMPILER_CLANG %\n", ifx os_target != .WINDOWS then 1 else 0); - - print_to_builder(*sb, "#define ARRAY_ENABLE_BOUNDS_CHECKING %\n", cast(s32)debug); - - append(*sb, "#define COMPILER_GCC 0\n"); - - meta_file_data := builder_to_string(*sb); - write_entire_file(META_GENERATED_HEADER_FILE_PATH, meta_file_data); - - print("Generated meta header at % for % on %\n", META_GENERATED_HEADER_FILE_PATH, cpu_target, os_target); -} - -#import "Basic"; -#import "BuildCpp"; -#import "Compiler"; -#import "File"; -#import "File_Utilities"; -#import "String"; -#import "System"; -#import "Process"; - -#if OS == .WINDOWS { - #import "Ico_File"; - #import "Windows_Resources"; - #import "Windows_Utf8"; -} -// Note: Other operating systems are not supported for this application (yet). - -FF :: (val: float64, width:=1) -> FormatFloat #expand { - return formatFloat(val, trailing_width = width, zero_removal=.NO); -} @Utility \ No newline at end of file diff --git a/build_imgui_lib.cmd b/build_imgui_lib.cmd deleted file mode 100644 index 29f0007..0000000 --- a/build_imgui_lib.cmd +++ /dev/null @@ -1,51 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -if "%~1"=="" ( - echo Usage: build_imgui_lib.cmd [Debug^|Release] - exit /b 1 -) - -set CONFIG=%~1 - -if /I "%CONFIG%"=="Debug" ( rem /Z7 embeds debug info into PDB so we don't need to pass /Fd to cl - set CFLAGS=/MTd /Od /Z7 /DDEBUG /DEBUG -diagnostics:caret -diagnostics:column -D_CRT_SECURE_NO_WARNINGS -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING -D_CRT_NONSTDC_NO_DEPRECATE -D_USE_MATH_DEFINES - set LIB_PATH=bin/Debug -) else if /I "%CONFIG%"=="Release" ( - set CFLAGS=/MT /O2 /DNDEBUG - set LIB_PATH=bin/Release -) else ( - echo Invalid configuration: %CONFIG% - echo Usage: build_imgui_lib.cmd [Debug^|Release] - exit /b 1 -) - -set OBJDIR=obj - -if not exist "%LIB_PATH%" mkdir "%LIB_PATH%" -if not exist obj mkdir obj - -set LIB_NAME=dear-imgui - -set SRC_FILES=^ - lib\third_party\dear-imgui\imgui.cpp ^ - lib\third_party\dear-imgui\imgui_widgets.cpp ^ - lib\third_party\dear-imgui\imgui_draw.cpp ^ - lib\third_party\dear-imgui\imgui_tables.cpp ^ - lib\third_party\dear-imgui\imgui_impl_dx11.cpp ^ - lib\third_party\dear-imgui\imgui_impl_win32.cpp - rem lib\third_party\dear-imgui\imgui_demo.cpp ^ - -set INCLUDE_DIRS=^ - /Ilib\third_party - -set LINK_LIBS= - -REM Build STATIC LIBRARY: rem /Fd%LIB_PATH%/%LIB_NAME%.pdb can be passed to cl if compiling with /Zi - echo Building static LIB (%CONFIG%) - cl /nologo /EHsc /DWIN32 /wd4530 %CFLAGS% %INCLUDE_DIRS% %SRC_FILES% /c /Fo%OBJDIR%\ - lib /OUT:%LIB_PATH%\%LIB_NAME%.lib %OBJDIR%\*.obj %LINK_LIBS% - -rd /s /q "%OBJDIR%" - -endlocal diff --git a/copy_files.cmd b/copy_files.cmd new file mode 100644 index 0000000..5e2da59 --- /dev/null +++ b/copy_files.cmd @@ -0,0 +1,17 @@ +@echo off +set CONFIG=%1 +echo Build configuration is: %CONFIG% + +if /i "%CONFIG%"=="Debug" ( + echo Copying files to debug directory + copy /Y "extras\fonts\RobotoMono-Regular.ttf" "build\Debug\RobotoMono-Regular.ttf" + copy /Y "extras\icons\tmp.ico" "build\Debug\tmp.ico" + copy /Y "extras\icons\tmp_min.ico" "build\Debug\tmp_min.ico" + :: #TODO: Copy DLLs: Varjo + rem copy /Y "third_party\bin\some_dll.dll" "build/Debug\some_dll.dll" +) else if /i "%CONFIG%"=="Release" ( + echo Copying files to release directory + copy /Y "extras\fonts\RobotoMono-Regular.ttf" "build\Release\RobotoMono-Regular.ttf" + copy /Y "extras\icons\tmp.ico" "build\Release\tmp.ico" + copy /Y "extras\icons\tmp_min.ico" "build\Release\tmp_min.ico" +) diff --git a/exe_main.cpp b/exe_main.cpp index 909adff..968d70a 100644 --- a/exe_main.cpp +++ b/exe_main.cpp @@ -1,6 +1,6 @@ +// Treat library files as a single-file header (single translation unit) #include "lib_main.cpp" -// Toggles: #define BASE_RUN_TESTS 0 #define BUILD_EXPLORER_APP_WIN32 1 #define BUILD_CUSTOM_GUI 0 @@ -17,6 +17,7 @@ #pragma comment(lib, "d3d11.lib") #pragma comment(lib, "dxgi.lib") + #pragma comment(lib, "msvcrt.lib") #include "lib/third_party/dear-imgui/imgui.h" #include "lib/third_party/dear-imgui/imgui_impl_win32.h" diff --git a/extras/imgui.ini b/extras/imgui.ini new file mode 100644 index 0000000..6e4d097 --- /dev/null +++ b/extras/imgui.ini @@ -0,0 +1,70 @@ +[Window][Debug##Default] +Pos=0,0 +Size=85,85 +Collapsed=0 + +[Window][Hello, world!] +Size=1582,874 +Collapsed=0 +DockId=0x00000002,0 + +[Window][Dear ImGui Demo] +Pos=0,22 +Size=2124,1511 +Collapsed=0 +DockId=0xC0DFADC4,0 + +[Window][DockSpace Demo] +Size=2560,1533 +Collapsed=0 + +[Window][Dear ImGui Metrics/Debugger] +ViewportPos=1947,173 +ViewportId=0x366E23FF +Size=435,462 +Collapsed=0 + +[Window][WindowOverViewport_11111111] +Pos=0,0 +Size=3391,1672 +Collapsed=0 + +[Window][Font Settings] +Pos=0,1556 +Size=1371,116 +Collapsed=0 +DockId=0x00000001,0 + +[Window][Test panel] +Pos=192,318 +Size=691,540 +Collapsed=0 + +[Window][Debug Panel] +Pos=1374,0 +Size=2017,1269 +Collapsed=0 +DockId=0x00000005,0 + +[Window][Control Panel] +Pos=1374,1272 +Size=2017,400 +Collapsed=0 +DockId=0x00000006,0 + +[Window][Enumerated Data Workspace] +Pos=0,0 +Size=1371,1672 +Collapsed=0 +DockId=0x00000002,0 + +[Docking][Data] +DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=225,261 Size=3391,1672 Split=X Selected=0x1FC7AC8C + DockNode ID=0x00000003 Parent=0x08BD597D SizeRef=1371,1672 Split=Y + DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1582,1553 CentralNode=1 Selected=0x671FC263 + DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1582,116 Selected=0x355F9D19 + DockNode ID=0x00000004 Parent=0x08BD597D SizeRef=2017,1672 Split=Y Selected=0xD2C573A7 + DockNode ID=0x00000005 Parent=0x00000004 SizeRef=1351,1269 Selected=0xD2C573A7 + DockNode ID=0x00000006 Parent=0x00000004 SizeRef=1351,400 Selected=0xF930105C +DockSpace ID=0xC0DFADC4 Pos=0,51 Size=2560,1511 CentralNode=1 Selected=0x5E5F7166 + diff --git a/lib/Base/Arena.cpp b/lib/Base/Arena.cpp index fa57883..80b4c6a 100644 --- a/lib/Base/Arena.cpp +++ b/lib/Base/Arena.cpp @@ -82,7 +82,11 @@ bool arena_commit_first_pages (Arena* arena, s64 commit_size, s64 start_offset) return true; } -Arena* bootstrap_arena (Arena_Reserve new_reserve, s32 default_commit_page_count) { +// Arena* bootstrap_arena (Arena_Reserve new_reserve, s32 default_commit_page_count) { +Arena* bootstrap_arena_internal (Arena_Reserve new_reserve, s32 default_commit_page_count, string file_path, + string function_name, s32 line_number) { + // + Save thread ID/name MAKE A COPY OBVIOUSLY! + PUSH default_allocator! + // WE USE default_allocator because this arena may be used to back an array! s64 commit_size = default_commit_page_count * PLATFORM_MEMORY_PAGE_SIZE; Assert(commit_size <= reserve_size(new_reserve)); @@ -93,11 +97,20 @@ Arena* bootstrap_arena (Arena_Reserve new_reserve, s32 default_commit_page_count return nullptr; } - memcpy(arena_ptr, &new_arena, sizeof(Arena)); + memcpy(arena_ptr, &new_arena, sizeof(Arena)); arena_ptr->current_point = arena_start(arena_ptr); arena_set_bootstrap_flag(arena_ptr); +#if BUILD_DEBUG + // #TODO: use thread_context()->stack_trace if present instead? + { arena_ptr->file_path = file_path; + arena_ptr->function_name = function_name; + arena_ptr->line_number = line_number; + add_arena_to_in_use_list(arena_ptr); + } +#endif + return arena_ptr; } @@ -309,4 +322,29 @@ void* fixed_arena_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 o } return nullptr; -} \ No newline at end of file +} + +force_inline void initialize_arenas_in_use_list () { +#if BUILD_DEBUG + if (arenas_in_use.allocated > 0) return; + mutex_init(&arenas_in_use_mutex); + arenas_in_use.allocator = default_allocator(); + array_reserve(arenas_in_use, 256); +#endif +} + +force_inline void add_arena_to_in_use_list (Arena* arena) { +#if BUILD_DEBUG + Assert(arenas_in_use.allocated > 0); // check we initialized! + lock_guard(&arenas_in_use_mutex); + array_add(arenas_in_use, arena); +#endif +} + +force_inline void remove_arena_from_in_use_list (Arena* arena) { +#if BUILD_DEBUG + Assert(arenas_in_use.allocated > 0); // check we initialized! + lock_guard(&arenas_in_use_mutex); + array_unordered_remove_by_value(arenas_in_use, arena, 1); +#endif +} diff --git a/lib/Base/Arena.h b/lib/Base/Arena.h index dcbd3d2..c066c8e 100644 --- a/lib/Base/Arena.h +++ b/lib/Base/Arena.h @@ -3,8 +3,8 @@ struct ExpandableArena; // fwd declare #temp #if OS_WINDOWS - constexpr u32 ARENA_DEFAULT_COMMIT_PAGE_COUNT = 16; // 16 * 4k page = 64kB - constexpr s64 ARENA_DEFAULT_COMMIT_SIZE_BYTES = 65536; + const u32 ARENA_DEFAULT_COMMIT_PAGE_COUNT = 16; // 16 * 4k page = 64kB + const s64 ARENA_DEFAULT_COMMIT_SIZE_BYTES = 65536; #endif constexpr u16 ARENA_DEFAULT_ALIGNMENT = CPU_REGISTER_WIDTH_BYTES; @@ -65,22 +65,30 @@ struct Arena { Arena_Reserve reserve_size = Arena_Reserve::Size_64K; Arena_Flags flags = Arena_Flags::None; u32 initial_commit_page_count = ARENA_DEFAULT_COMMIT_PAGE_COUNT; +#if BUILD_DEBUG + string file_path; + string function_name; + s32 line_number; +#endif }; typedef void* (*Memory_Wipe_Function)(void* memory, u64 byte_count); void* arena_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data); -// Interface API for normal use (idk how to explain - see Arena_Free_List.cpp) - -void initialize_arena_free_list (Allocator allocator); -Arena* next_arena (Arena_Reserve reserve_size); -void release_arena (Arena* arena, bool delete_extra_pages=true); - // Main API -Arena* bootstrap_arena (Arena_Reserve new_reserve, s32 default_commit_page_count); +#if BUILD_DEBUG +#define bootstrap_arena(_reserve_) \ + bootstrap_arena_internal((_reserve_), (s32)ARENA_DEFAULT_COMMIT_PAGE_COUNT, __FILE__, __FUNCTION__, __LINE__) +#else +#define bootstrap_arena(_reserve_) \ + bootstrap_arena_internal((_reserve_), (s32)ARENA_DEFAULT_COMMIT_PAGE_COUNT) +#endif -void arena_init (Arena* arena, Arena_Reserve new_reserve, s32 default_commit_page_count=16); // For when we're *not* bootstrapping arenas: (I'm debating if we should keep this..) +Arena* bootstrap_arena_internal (Arena_Reserve new_reserve, s32 commit_page_count=ARENA_DEFAULT_COMMIT_PAGE_COUNT, + string file_path="", string function_name="", s32 line_number=0); + +void arena_init (Arena* arena, Arena_Reserve new_reserve, s32 commit_page_count=16); // For when we're *not* bootstrapping arenas: (I'm debating if we should keep this..) bool arena_commit_first_pages (Arena* arena, s64 commit_size, s64 start_offset=0); // This is useful for initializing arenas (arena_init), and for starting Arena-backed arrays. void arena_clear_flags (Arena* arena); @@ -142,7 +150,7 @@ struct Push_Alignment { // #rename to Arena_Push_Alignment? // #FixedArena is a super simple arena where you allocate a fixed block up front (fully committed), // and use it as-is. -// #NOTE: we can save space be always backing with a known allocator (e.g. GPAllocator()). +// #NOTE: we can save space be always backing with a known allocator (e.g. default_allocator()). struct FixedArena { ArrayView memory; s64 cursor; @@ -152,6 +160,36 @@ struct FixedArena { void* fixed_arena_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data); // #FixedArena API -FixedArena* bootstrap_fixed_arena (s64 size, Allocator backing_allocator); +FixedArena* bootstrap_fixed_arena (s64 size, Allocator backing_allocator = { default_allocator_proc, nullptr }); force_inline void destroy_arena (FixedArena* arena); Allocator allocator (FixedArena* arena); + +s64 bytes_in_use (ArrayView arenas) { + // does not include overhead from committed pages! + s64 sum = 0; + + for (s64 i = 0; i < arenas.count; i += 1) { + sum += arena_usage_bytes(arenas[i]); + } + + return sum; +} + +s64 committed_bytes (ArrayView arenas) { + s64 sum = 0; + + for (s64 i = 0; i < arenas.count; i += 1) { + sum += arena_usage_committed_bytes(arenas[i]); + } + + return sum; +} + +#if BUILD_DEBUG + global Mutex arenas_in_use_mutex; + global Array arenas_in_use; + + force_inline void initialize_arenas_in_use_list (); + force_inline void add_arena_to_in_use_list(Arena* arena); + force_inline void remove_arena_from_in_use_list (Arena* arena); +#endif diff --git a/lib/Base/Arena_Array.h b/lib/Base/Arena_Array.h index a1755ce..2a192e5 100644 --- a/lib/Base/Arena_Array.h +++ b/lib/Base/Arena_Array.h @@ -1,6 +1,10 @@ #pragma once +#if BUILD_DEBUG +constexpr s64 ARRAY_ARENA_START_OFFSET = 2 * 64; // sizeof(Arena)+sizeof(array) +#else constexpr s64 ARRAY_ARENA_START_OFFSET = 64; +#endif template struct ArenaArray { // #downcasts to an ArrayView. @@ -28,7 +32,7 @@ struct ArenaArray { // #downcasts to an ArrayView. // Use arena_array_free to reset template ArenaArray* arena_array_new (s64 preallocate_count, Arena_Reserve reserve_size) { - Arena* arena = next_arena(reserve_size); + Arena* arena = bootstrap_arena(reserve_size); push_arena(arena); push_alignment(arena, 1); ArenaArray* array = New>(true); @@ -41,13 +45,22 @@ ArenaArray* arena_array_new (s64 preallocate_count, Arena_Reserve reserve_siz array->count = 0; array->arena = arena; + // #TODO: Should align to next cache line! array->data = array_start(*array); return array; } template T* array_start (ArenaArray& array) { - return (T*)(array.arena->memory_base + ARRAY_ARENA_START_OFFSET); + T* memory = (T*)(array.arena->memory_base + ARRAY_ARENA_START_OFFSET); + Assert((u8*)memory >= (u8*)array.arena->current_point); + return memory; +} + +s64 max_array_size (ArenaArray& array) { + u8* address_limit = array.arena->memory_base + reserve_size(array.arena); + u8* address_start = array_start(array); + return (s64)(address_limit - address_start); } template bool is_valid (ArenaArray* array) { @@ -65,12 +78,8 @@ template s64 memory_usage (ArenaArray& array) { return arena_usage_committed_bytes(array.arena); } -template void arena_array_free (ArenaArray& array, bool delete_pages=true) { - release_arena(array.arena, delete_pages); - array.arena = nullptr; -#if BUILD_DEBUG - poison_struct(&array); -#endif +template void arena_array_free (ArenaArray& array) { + arena_delete(array.arena); } template ArrayView array_view (ArenaArray array) { @@ -164,10 +173,6 @@ template void array_resize (ArenaArray& array, s64 desired_item_ } } -s64 max_array_size (ArenaArray& array) { - return reserve_size(array.arena) - sizeof(Arena) - sizeof(ArenaArray); -} - void array_arena_realloc (ArenaArray& array, s64 new_size, s64 old_size) { Assert(new_size <= max_array_size(array)); @@ -204,6 +209,7 @@ template void init_range (T* ptr, s64 start_offset, s64 end_offset) template void array_poison_range (ArenaArray& array, s64 start, s64 count) { #if BUILD_DEBUG + if (count == 0) return; Assert(start >= 0 && start < array.count); Assert(start + count <= array.count); // Check that these ranges make sense diff --git a/lib/Base/Arena_Free_List.cpp b/lib/Base/Arena_Free_List.cpp deleted file mode 100644 index 0cf87d1..0000000 --- a/lib/Base/Arena_Free_List.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// #TODO: #Arena_Free_List #garbage_collection in `release_arena` -// [ ] Garbage collection if we have >> 64 in a particular table for a while. -// There should be some parameters regarding what the upper limit for idle -// committed pages should be and a heuristic for maximum number of arenas waiting - -struct Arena_Free_List { - Mutex mutex; - s32 in_flight_count[Arena_Reserve_Count]; - Array free_table[Arena_Reserve_Count]; - -#if ARENA_DEBUG - Array in_flight[Arena_Reserve_Count]; -#endif - b32 initialized; -}; - -global Arena_Free_List* arena_free_list; - -// Only call once from main thread! -void initialize_arena_free_list (Allocator allocator) { - mutex_init(&arena_free_list->mutex); - Assert(arena_free_list != nullptr); - if (arena_free_list->initialized) - return; - - for (s32 i = 0; i < Arena_Reserve_Count; i += 1) { - arena_free_list->in_flight_count[i] = 0; - arena_free_list->free_table[i].allocator = allocator; - array_reserve(arena_free_list->free_table[i], 64); -#if ARENA_DEBUG - arena_free_list->in_flight[i].allocator = allocator; - array_reserve(arena_free_list->in_flight[i], 64); -#endif - } - - arena_free_list->initialized = true; -} - -Arena* next_arena (Arena_Reserve reserve_size) { - Assert(arena_free_list != nullptr); - Arena* arena; - lock_guard(&arena_free_list->mutex); - s64 reserve_index = (s64)reserve_size; - - if (!arena_free_list->free_table[reserve_index].count) { - arena = bootstrap_arena(reserve_size, ARENA_DEFAULT_COMMIT_PAGE_COUNT); - } else { - arena = pop(arena_free_list->free_table[reserve_index]); - } -#if ARENA_DEBUG - array_add(arena_free_list->in_flight[reserve_index], arena); -#endif - - arena_free_list->in_flight_count[reserve_index] += 1; - - Assert(arena != nullptr); - return arena; -} - -void release_arena (Arena* arena, bool delete_extra_pages) { - Assert(arena_free_list != nullptr); - Assert(arena != nullptr); - Assert(arena_is_bootstrapped(arena)); - // Only put into free table if arena is bootstrapped? - lock_guard(&arena_free_list->mutex); - s64 reserve_index = (s64)arena->reserve_size; - -#if ARENA_DEBUG - array_unordered_remove_by_value(arena_free_list->in_flight[reserve_index], arena, 1); // BUILD_DEBUG! -#endif - arena_reset_keeping_memory(arena); - if (delete_extra_pages) { - free_pages_down_to(arena, arena->initial_commit_page_count); - } - array_add(arena_free_list->free_table[reserve_index], arena); - - arena_free_list->in_flight_count[reserve_index] -= 1; - // #TODO #garbage_collection - // if (arena_free_table[reserve_index].count > 64) { - // s64 arenas_to_delete_count = arena_free_table[reserve_index].count - 64; - // while (arenas_to_delete_count > 0) { - // arena_delete(arena_free_table[arena_free_table.count-1]); - // array_unordered_remove_by_index(..); - // arenas_to_delete_count -= 1; - // } - // } -} - -s64 bytes_in_use (ArrayView arenas) { - // does not include overhead from committed pages! - s64 sum = 0; - - for (s64 i = 0; i < arenas.count; i += 1) { - sum += arena_usage_bytes(arenas[i]); - } - - return sum; -} - -s64 committed_bytes (ArrayView arenas) { - s64 sum = 0; - - for (s64 i = 0; i < arenas.count; i += 1) { - sum += arena_usage_committed_bytes(arenas[i]); - } - - return sum; -} diff --git a/lib/Base/Arena_Windows.cpp b/lib/Base/Arena_Windows.cpp index e0e5bbd..5c7bbe2 100644 --- a/lib/Base/Arena_Windows.cpp +++ b/lib/Base/Arena_Windows.cpp @@ -60,6 +60,14 @@ void free_pages_down_to (Arena* arena, s64 pages_to_keep) { void arena_delete (Arena* arena) { if (!is_valid(arena)) return; + +#if BUILD_DEBUG + { //default_allocator_free(arena->file_path.data); + //default_allocator_free(arena->function_name.data); + remove_arena_from_in_use_list(arena); + } +#endif + bool arena_was_boostrapped = (arena->flags & Arena_Flags::Is_Bootstrapped) == Arena_Flags::Is_Bootstrapped; // s64 size_tmp = reserve_size(arena); diff --git a/lib/Base/Array.h b/lib/Base/Array.h index 4d4b34c..203340b 100644 --- a/lib/Base/Array.h +++ b/lib/Base/Array.h @@ -235,7 +235,6 @@ void array_unordered_remove_by_index (Array& src, s64 index) { template s64 array_unordered_remove_by_value (Array& src, T item, s64 max_count_to_remove) { s64 removed_count = 0; - for (s64 i = 0; i < src.count; i += 1) { if (src[i] == item) { removed_count += 1; diff --git a/lib/Base/Base.h b/lib/Base/Base.h index ec4a377..dadda52 100644 --- a/lib/Base/Base.h +++ b/lib/Base/Base.h @@ -1,6 +1,161 @@ #pragma once -#define LANG_CPP 1 +// Some of these macros are ""borrowed"" from nick aversano | source: https://github.com/nickav/na/blob/main/na.h + +// #OS_Platform +#if defined(_WIN32) + #define OS_WINDOWS 1 +#elif defined(__APPLE__) + #define OS_MACOS 1 +#elif defined(__linux__) + #define OS_LINUX 1 +#endif + +#if !defined(OS_WINDOWS) + #define OS_WINDOWS 0 +#endif +#if !defined(OS_LINUX) + #define OS_LINUX 0 +#endif +#if !defined(OS_MACOS) + #define OS_MACOS 0 +#endif + +#if defined(__cplusplus) + #define LANG_CPP 1 +#else + #define LANG_C 1 +#endif + +// #Compiler: Language +#if !defined(LANG_CPP) + #define LANG_CPP 0 +#endif +#if !defined(LANG_C) + #define LANG_C 0 +#endif + +// #Compiler: Vendor +#if defined(__clang__) + #define COMPILER_CLANG 1 +#elif defined(_MSC_VER) + #define COMPILER_MSVC 1 +#elif defined(__GNUC__) || defined(__GNUG__) + #define COMPILER_GCC 1 +#endif + +#if !defined(COMPILER_MSVC) + #define COMPILER_MSVC 0 +#endif +#if !defined(COMPILER_GCC) + #define COMPILER_GCC 0 +#endif +#if !defined(COMPILER_CLANG) + #define COMPILER_CLANG 0 +#endif + +#if COMPILER_MSVC + #if _MSC_VER >= 1930 + #define COMPILER_MSVC_YEAR 2022 + #elif _MSC_VER >= 1920 + #define COMPILER_MSVC_YEAR 2019 + #elif _MSC_VER >= 1910 + #define COMPILER_MSVC_YEAR 2017 + #elif _MSC_VER >= 1900 + #define COMPILER_MSVC_YEAR 2015 + #elif _MSC_VER >= 1800 + #define COMPILER_MSVC_YEAR 2013 + #elif _MSC_VER >= 1700 + #define COMPILER_MSVC_YEAR 2012 + #elif _MSC_VER >= 1600 + #define COMPILER_MSVC_YEAR 2010 + #elif _MSC_VER >= 1500 + #define COMPILER_MSVC_YEAR 2008 + #elif _MSC_VER >= 1400 + #define COMPILER_MSVC_YEAR 2005 + #else + #define COMPILER_MSVC_YEAR 0 + #endif +#endif + +// #Architecture: CPU Vendor +#if defined(_WIN32) + #if defined(_M_AMD64) + #define ARCH_CPU_X64 1 + #elif defined(_M_IX86) + #define ARCH_CPU_X86 1 + #elif defined(_M_ARM64) + #define ARCH_CPU_ARM64 1 + #elif defined(_M_ARM) + #define ARCH_CPU_ARM32 1 + #endif + +#else + #if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) + #define ARCH_CPU_X64 1 + #elif defined(i386) || defined(__i386) || defined(__i386__) + #define ARCH_CPU_X86 1 + #elif defined(__aarch64__) + #define ARCH_CPU_ARM64 1 + #elif defined(__arm__) + #define ARCH_CPU_ARM32 1 + #endif + +#endif + +#if !defined(ARCH_CPU_X64) + #define ARCH_CPU_X64 0 +#endif +#if !defined(ARCH_CPU_X86) + #define ARCH_CPU_X86 0 +#endif +#if !defined(ARCH_CPU_ARM64) + #define ARCH_CPU_ARM64 0 +#endif +#if !defined(ARCH_CPU_ARM32) + #define ARCH_CPU_ARM32 0 +#endif + +// #Architecture: Register Width +#if defined(ARCH_CPU_X64) || defined(ARCH_CPU_ARM64) + #define ARCH_64BIT 1 +#elif defined(ARCH_CPU_X86) || defined(ARCH_CPU_ARM32) + #define ARCH_32BIT 1 +#endif + +#if !defined(ARCH_64BIT) + #define ARCH_64BIT 0 +#endif +#if !defined(ARCH_32BIT) + #define ARCH_32BIT 0 +#endif + +// #Architecture: Endianness +static const int __arch_endian_check_num = 1; + +#define ARCH_LITTLE_ENDIAN (*(char *)&__arch_endian_check_num == 1) +#define ARCH_BIG_ENDIAN (!ARCH_LITTLE_ENDIAN) + +#if defined(_MSC_VER) + #ifdef _DEBUG + #define BUILD_DEBUG 1 + #else + #define BUILD_DEBUG 0 + #endif +#elif defined(__GNUC__) || defined(__clang__) + #ifndef NDEBUG + #define BUILD_DEBUG 1 + #else + #define BUILD_DEBUG 0 + #endif +#endif + +// #ifndef NDEBUG +// #define BUILD_DEBUG 1 +// #else +// #define BUILD_DEBUG 0 +// #endif + #define BUILD_CONSOLE_INTERFACE BUILD_DEBUG #include // vsnprintf @@ -191,6 +346,7 @@ force_inline s64 Next_Power_Of_Two(s64 v) { #define temp() allocator(thread_context()->temp) #define context_allocator() thread_context()->allocator #define context_logger() &thread_context()->logger +#define context_builder() thread_context()->string_builder // CHECK THAT THESE ARE CORRECT! constexpr f32 TAU = 6.283185f; diff --git a/lib/Base/Base_Thread_Context.cpp b/lib/Base/Base_Thread_Context.cpp index 5fda429..3e1a480 100644 --- a/lib/Base/Base_Thread_Context.cpp +++ b/lib/Base/Base_Thread_Context.cpp @@ -3,24 +3,33 @@ internal void Bootstrap_Main_Thread_Context () { // Timed_Block_Print_No_Context("Bootstrap_Main_Thread_Context"); // 0. Setup general allocator - GPAllocator_Initialize_Allocation_Tracker(); + default_allocator_Initialize_Allocation_Tracker(); - // 1. Setup arena table - arena_free_list = (Arena_Free_List*)GPAllocator_New(sizeof(Arena_Free_List), 64, true); // permanent allocation. - memset(arena_free_list, 0, sizeof(Arena_Free_List)); - initialize_arena_free_list(GPAllocator()); + // 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 = expandable_arena_new(Arena_Reserve::Size_64M, 16); + ExpandableArena* arena_ex = bootstrap_expandable_arena(Arena_Reserve::Size_64M); thread_local_context = New(allocator(arena_ex)); - thread_local_context->temp = expandable_arena_new(Arena_Reserve::Size_2M, 16); - 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"; - thread_local_context->log_builder = new_string_builder(Arena_Reserve::Size_64M); - thread_local_context->error_arena = next_arena(Arena_Reserve::Size_64M); + thread_local_context->temp = bootstrap_expandable_arena(Arena_Reserve::Size_2M); + 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"; + thread_local_context->log_builder = new_string_builder(Arena_Reserve::Size_64M); + thread_local_context->string_builder = new_string_builder(Arena_Reserve::Size_2M); + thread_local_context->error_arena = bootstrap_arena(Arena_Reserve::Size_64M); default_logger_initialize(); thread_local_context->logger = {default_logger_proc, &default_logger}; @@ -55,6 +64,7 @@ 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); diff --git a/lib/Base/Base_Thread_Context.h b/lib/Base/Base_Thread_Context.h index 2290b5a..ce48a8b 100644 --- a/lib/Base/Base_Thread_Context.h +++ b/lib/Base/Base_Thread_Context.h @@ -1,4 +1,17 @@ // #hacky fwd declares +struct Source_Code_Location { + string file_name; + string function_name; + s32 line_number; +}; + +struct Stack_Trace_Node { + Stack_Trace_Node* next; + // Information + Source_Code_Location data; + s32 call_depth; +}; + struct Error; struct Graphics; @@ -9,17 +22,18 @@ struct Thread_Context { Allocator allocator; s32 thread_idx; // u16 _padding0; - u16 GPAllocator_alignment = 16; + u16 default_allocator_alignment = 16; Logger logger = {nullptr, nullptr}; - String_Builder* log_builder; - // Stack_Trace* stack_trace; + String_Builder* log_builder; // String builder used by log() and log_error_internal() + String_Builder* string_builder; // Secondary builder just for convenience! + Stack_Trace_Node* stack_trace; // use `list(stack_trace)` in watch window of raddbg to view as array! Array child_threads; // maybe should be linked-list? Thread_Context* parent_thread_context = nullptr; // so we can remove from above array string thread_name; - Allocator error_allocator = GPAllocator(); + Allocator error_allocator = default_allocator(); Error* first_error = nullptr; Error* current_error = nullptr; Arena* error_arena; @@ -44,12 +58,118 @@ struct Push_Allocator { Push_Allocator (Allocator new_allocator) { context = thread_context(); - old_allocator = context->allocator; - context->allocator = new_allocator; + if (this->context != nullptr) { + old_allocator = context->allocator; + context->allocator = new_allocator; + } else { + old_allocator = default_allocator(); + } } ~Push_Allocator () { - context->allocator = old_allocator; + if (this->context != nullptr) { + context->allocator = old_allocator; + } } }; +// #stack_trace +#define ENABLE_STACK_TRACE BUILD_DEBUG + +void push_stack_trace_internal (Thread_Context* context, string file_name, string function_name, s32 line_number) { + if (context == nullptr) return; + Assert(context != nullptr); + // #no_context allocation + Stack_Trace_Node* new_node = (Stack_Trace_Node*)default_allocator_new(sizeof(Stack_Trace_Node)); + + new_node->data.file_name = file_name; + new_node->data.function_name = function_name; + new_node->data.line_number = line_number; + new_node->next = nullptr; + + if (context->stack_trace == nullptr) { + new_node->call_depth = 1; + + } else { + new_node->call_depth = context->stack_trace->call_depth + 1; + + new_node->next = context->stack_trace; + } + + context->stack_trace = new_node; +} + +void pop_stack_trace_internal (Thread_Context* context) { + if (context == nullptr) return; + Stack_Trace_Node* old_node = context->stack_trace; + context->stack_trace = old_node->next; + + default_allocator_free(old_node); +} + +#if ENABLE_STACK_TRACE +#define stack_trace() \ + Push_Stack_Trace Concat(_push_stack_trace_guard_, __LINE__)(__FILE__, __FUNCTION__, __LINE__) +#else +#define stack_trace() +#endif + +struct Push_Stack_Trace { + Thread_Context* context; + + Push_Stack_Trace (string file_name, string function_name, s32 line_number) { + context = thread_context(); + push_stack_trace_internal(context, file_name, function_name, line_number); + } + + ~Push_Stack_Trace () { + pop_stack_trace_internal(context); + } +}; + +// #TODO: precede with something like: os_write_string_unsynchronized("Fatal Error!\n\nStack trace:", true); +string generate_stack_trace (Thread_Context* context) { + // #no_context - we want this to work even if context is utterly broken. + String_Builder* sb = new_string_builder(Arena_Reserve::Size_64K); + + Stack_Trace_Node* node = context->stack_trace; + + print_to_builder(sb, "Thread index: %d, thread name: %s\n\n", context->thread_idx, context->thread_name.data); + + while (node) { + append(sb, format_string("%s:%d: %s\n", node->data.file_name.data, node->data.line_number, node->data.function_name.data)); + + node = node->next; + } + + append(sb, "\n"); + + push_allocator(default_allocator()); + + string stack_trace_copy = builder_to_string(sb); + + free_string_builder(sb); + + return stack_trace_copy; +} + +// We don't want to use context logger here! +void print_stack_trace () { + Thread_Context* context = thread_context(); + + Stack_Trace_Node* node = context->stack_trace; + + constexpr bool TO_STANDARD_ERROR = true; + + os_write_string_unsynchronized(generate_stack_trace(context), TO_STANDARD_ERROR); + // while (node) { + // os_write_string_unsynchronized(node->data.file_name, TO_STANDARD_ERROR); + // string line_number_str = format_string(":%d: ", node->data.line_number); // maybe I shouldn't do this? + // os_write_string_unsynchronized(line_number_str, TO_STANDARD_ERROR); + // // os_write_string_unsynchronized("'", TO_STANDARD_ERROR); + // os_write_string_unsynchronized(node->data.function_name, TO_STANDARD_ERROR); + // os_write_string_unsynchronized("\n", TO_STANDARD_ERROR); + + // node = node->next; + // } +} diff --git a/lib/Base/ErrorType.cpp b/lib/Base/ErrorType.cpp index 47c3d68..2c20e16 100644 --- a/lib/Base/ErrorType.cpp +++ b/lib/Base/ErrorType.cpp @@ -54,19 +54,19 @@ string to_string (Error* error) { } #define log_todo(fmt, ...) \ - Log_Error_2(__FILE__, __FUNCTION__, __LINE__, ErrorClass::TODO, fmt, ##__VA_ARGS__) + log_error_internal(__FILE__, __FUNCTION__, __LINE__, ErrorClass::TODO, fmt, ##__VA_ARGS__) #define log_fatal_error(fmt, ...) \ - Log_Error_2(__FILE__, __FUNCTION__, __LINE__, ErrorClass::FATAL, fmt, ##__VA_ARGS__) + log_error_internal(__FILE__, __FUNCTION__, __LINE__, ErrorClass::FATAL, fmt, ##__VA_ARGS__) #define log_error(fmt, ...) \ - Log_Error_2(__FILE__, __FUNCTION__, __LINE__, ErrorClass::ERROR, fmt, ##__VA_ARGS__) + log_error_internal(__FILE__, __FUNCTION__, __LINE__, ErrorClass::ERROR, fmt, ##__VA_ARGS__) #define log_warning(fmt, ...) \ - Log_Error_2(__FILE__, __FUNCTION__, __LINE__, ErrorClass::WARNING, fmt, ##__VA_ARGS__) + log_error_internal(__FILE__, __FUNCTION__, __LINE__, ErrorClass::WARNING, fmt, ##__VA_ARGS__) #define log_none(fmt, ...) \ - Log_Error_2(__FILE__, __FUNCTION__, __LINE__, ErrorClass::NONE, fmt, ##__VA_ARGS__) + log_error_internal(__FILE__, __FUNCTION__, __LINE__, ErrorClass::NONE, fmt, ##__VA_ARGS__) Error* new_error (ErrorClass severity, string error_string) { Error* error = New(); @@ -77,12 +77,12 @@ Error* new_error (ErrorClass severity, string error_string) { return error; } -void Log_Error_2 (string file_path, string function_name, s32 line_number, ErrorClass severity, string fmt, ...) { +void log_error_internal (string file_path, string function_name, s32 line_number, ErrorClass severity, string fmt, ...) { auto tctx = thread_context(); Assert(tctx != nullptr); push_arena(tctx->error_arena); - String_Builder* sb = new_string_builder(Arena_Reserve::Size_64K); + String_Builder* sb = thread_context()->log_builder; print_to_builder(sb, "%s ", error_severity(severity)); @@ -93,7 +93,10 @@ void Log_Error_2 (string file_path, string function_name, s32 line_number, Error append(sb, "\n"); - string error_string = builder_to_string(sb); + string error_string = copy_string(string_view(sb)); + + reset_string_builder(sb); + Error* error = new_error(severity, error_string); // Additional information error->thread_id = tctx->thread_idx; diff --git a/lib/Base/Expandable_Arena.cpp b/lib/Base/Expandable_Arena.cpp index 5f5702f..a6f480f 100644 --- a/lib/Base/Expandable_Arena.cpp +++ b/lib/Base/Expandable_Arena.cpp @@ -1,5 +1,11 @@ -ExpandableArena* expandable_arena_new (Arena_Reserve starting_reserve, s32 commit_page_count) { - ExpandableArena* new_arena = (ExpandableArena*)bootstrap_arena(starting_reserve, commit_page_count); +ExpandableArena* bootstrap_expandable_arena_internal (Arena_Reserve new_reserve, s32 commit_page_count, + string file_path, string function_name, s32 line_number) { + ExpandableArena* new_arena = (ExpandableArena*)bootstrap_arena_internal( + new_reserve, + commit_page_count, + file_path, + function_name, + line_number); // Note: beyond first 32 bytes (sizeof(Arena)) ExpandableArena will not be initialized, // so we do it here: new_arena->current = (Arena*)new_arena; @@ -8,13 +14,17 @@ ExpandableArena* expandable_arena_new (Arena_Reserve starting_reserve, s32 commi new_arena->next_arenas = Array(); // next_arenas will be uninitialized, so we have to do this // We have to use malloc because if we reset this new arena, all the data will be lost // We don't want to tie the lifetime of next_arenas to this expandable arena. - new_arena->next_arenas.allocator = GPAllocator(); + new_arena->next_arenas.allocator = default_allocator(); array_reserve(new_arena->next_arenas, 8); return new_arena; } +// force_inline ExpandableArena* bootstrap_expandable_arena (Arena_Reserve new_reserve, s32 commit_page_count) { +// return bootstrap_expandable_arena_internal(new_reserve, commit_page_count, __FILE__, __FUNCTION__, __LINE__); +// } + void* expandable_arena_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data) { ExpandableArena* arena = (ExpandableArena*)allocator_data; Assert(arena != nullptr); @@ -58,7 +68,7 @@ void* expandable_arena_alloc (ExpandableArena* arena_ex, s64 byte_count) { Assert(arena_ex != nullptr); Assert(arena_ex->memory_base != nullptr); // must be initialized before calling. Assert(is_valid(arena_ex)); - Assert(arena_free_list->initialized); + // Assert(arena_free_list->initialized); Arena* arena = (Arena*)arena_ex->current; @@ -73,7 +83,7 @@ void* expandable_arena_alloc (ExpandableArena* arena_ex, s64 byte_count) { new_min_reserve = arena->reserve_size; } - Arena* new_arena = next_arena(new_min_reserve); + Arena* new_arena = bootstrap_arena(new_min_reserve); new_arena->alignment = arena_ex->alignment; new_arena->flags = arena_ex->flags; @@ -106,8 +116,7 @@ Allocator allocator (ExpandableArena* arena_ex) { return { expandable_arena_allocator_proc, arena_ex }; } -// #TODO: currently this keeps the final arena's memory. Fix this! -// This is not implemented correctly! +// last arena is the arena we want to pop to. void arena_reset_to (ExpandableArena* arena_ex, Arena* last_arena, u8* starting_point) { // going backwards from end of arena list @@ -116,7 +125,6 @@ void arena_reset_to (ExpandableArena* arena_ex, Arena* last_arena, u8* starting_ return; } - // for (s64 i = arena_ex->next_arenas.count-1; i >= 0; i -= 1) { for_each_reverse(i, arena_ex->next_arenas) { Arena* arena = arena_ex->next_arenas[i]; if (arena == last_arena) { // return to starting_point @@ -124,8 +132,14 @@ void arena_reset_to (ExpandableArena* arena_ex, Arena* last_arena, u8* starting_ arena_ex->current->current_point = starting_point; break; } - release_arena(arena); - array_unordered_remove_by_index(arena_ex->next_arenas, i); + arena_delete(arena); + // We can just decrement the count because arenas are added and removed in order. see: pop() + arena_ex->next_arenas.count -= 1; + } + + if (last_arena == (Arena*)arena_ex) { + arena_ex->current = (Arena*)arena_ex; + arena_ex->current->current_point = starting_point; } } @@ -134,7 +148,7 @@ void arena_reset (ExpandableArena* arena_ex, bool free_extra_pages) { // Free expansion arenas in `next_arenas` for (s64 i = 0; i < arena_ex->next_arenas.count; i += 1) { - release_arena(arena_ex->next_arenas[i], free_extra_pages); + arena_delete(arena_ex->next_arenas[i]); } // Reset next_arenas diff --git a/lib/Base/Expandable_Arena.h b/lib/Base/Expandable_Arena.h index 776b8e0..92ba9bf 100644 --- a/lib/Base/Expandable_Arena.h +++ b/lib/Base/Expandable_Arena.h @@ -5,25 +5,28 @@ // DO NOT MERGE WITH `Arena`, we need fixed size arenas so that we can back // `ArenaArray`s. -struct ExpandableArena { - u8* current_point = nullptr; - u8* memory_base = nullptr; - u8* first_uncommitted_page = nullptr; - u16 alignment = CPU_REGISTER_WIDTH_BYTES; - Arena_Reserve reserve_size = Arena_Reserve::Size_64K; - Arena_Flags flags = Arena_Flags::None; - u32 initial_commit_page_count = ARENA_DEFAULT_COMMIT_PAGE_COUNT; - // Note that this downcasts to Arena*, so can be initialized in the same way. +struct ExpandableArena : Arena { Arena* current; Array next_arenas; }; -ExpandableArena* expandable_arena_new (Arena_Reserve starting_reserve=Arena_Reserve::Size_64K, s32 commit_page_count=8); +#if BUILD_DEBUG +#define bootstrap_expandable_arena(_reserve_) \ + bootstrap_expandable_arena_internal((_reserve_), (s32)ARENA_DEFAULT_COMMIT_PAGE_COUNT, __FILE__, __FUNCTION__, __LINE__) +#else +#define bootstrap_expandable_arena(_reserve_) \ + bootstrap_expandable_arena_internal((_reserve_), (s32)ARENA_DEFAULT_COMMIT_PAGE_COUNT) +#endif + +ExpandableArena* bootstrap_expandable_arena_internal (Arena_Reserve new_reserve=Arena_Reserve::Size_64K, s32 commit_page_count=ARENA_DEFAULT_COMMIT_PAGE_COUNT, + string file_path="", string function_name="", s32 line_number=0); + +// ExpandableArena* bootstrap_expandable_arena_internal (Arena_Reserve starting_reserve=Arena_Reserve::Size_64K, s32 commit_page_count=8); void* expandable_arena_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data); bool is_valid (ExpandableArena* arena); void* expandable_arena_alloc (ExpandableArena* arena_ex, s64 byte_count); u8* expandable_arena_start (ExpandableArena* arena_ex); Allocator allocator (ExpandableArena* arena_ex); void arena_reset_to (ExpandableArena* arena_ex, Arena* last_arena, u8* starting_point); -void arena_reset (ExpandableArena* arena_ex, bool free_extra_pages=true); +void arena_reset (ExpandableArena* arena_ex, bool free_extra_pages); force_inline void arena_delete (ExpandableArena* arena_ex); diff --git a/lib/Base/General_Purpose_Allocator.cpp b/lib/Base/General_Purpose_Allocator.cpp index e5fa7c5..f2b985c 100644 --- a/lib/Base/General_Purpose_Allocator.cpp +++ b/lib/Base/General_Purpose_Allocator.cpp @@ -1,6 +1,7 @@ #if GP_ALLOCATOR_TRACK_ALLOCATIONS global General_Allocator gAllocator; // @Shared global Mutex allocator_mutex; + global bool default_allocator_show_small_allocations = true; #endif #if !COMPILER_MSVC @@ -32,23 +33,23 @@ General_Allocator* get_general_allocator_data() { constexpr s64 Allocation_Tracking_Is_Enabled = GP_ALLOCATOR_TRACK_ALLOCATIONS; -bool GPAllocator_Tracking_Enabled () { +bool default_allocator_Tracking_Enabled () { return Allocation_Tracking_Is_Enabled != 0; } -void GPAllocator_Initialize_Allocation_Tracker () { +void default_allocator_Initialize_Allocation_Tracker () { #if GP_ALLOCATOR_TRACK_ALLOCATIONS mutex_init(&allocator_mutex); constexpr s64 alignment = 64; s64 item_count_max = 64 * 4096; s64 total_allocation_size = item_count_max * sizeof(Allocation); auto memory = Aligned_Alloc(total_allocation_size, alignment); // @MemoryLeak (intentional) - gAllocator.allocations = Array(item_count_max, memory, item_count_max, GPAllocator()); + gAllocator.allocations = Array(item_count_max, memory, item_count_max, default_allocator()); gAllocator.allocations.count = 0; // Init to zero. #endif } -bool GPAllocator_Is_This_Yours (void* old_memory) { +bool default_allocator_Is_This_Yours (void* old_memory) { #if GP_ALLOCATOR_TRACK_ALLOCATIONS lock_guard(&allocator_mutex); @@ -94,7 +95,7 @@ void Remove_Allocation(void* old_memory) { #endif } -void* GPAllocator_New (s64 new_size, s64 alignment, bool initialize) { +void* default_allocator_new (s64 new_size, s64 alignment, bool initialize) { // Fallback allocator: _aligned_malloc, which is MSVC's version of std::aligned_alloc auto memory = Aligned_Alloc(new_size, alignment); @@ -107,11 +108,11 @@ void* GPAllocator_New (s64 new_size, s64 alignment, bool initialize) { return memory; } -void* GPAllocator_Resize (s64 old_size, void* old_memory, s64 new_size, s64 alignment, bool initialize) { +void* default_allocator_realloc (s64 old_size, void* old_memory, s64 new_size, s64 alignment, bool initialize) { Assert((alignment % 8) == 0 && (alignment != 0)); if (old_memory == nullptr) { - return GPAllocator_New(new_size, alignment); + return default_allocator_new(new_size, alignment); } // Debug version: _aligned_realloc_dbg @@ -128,7 +129,7 @@ void* GPAllocator_Resize (s64 old_size, void* old_memory, s64 new_size, s64 alig return new_memory_address; } -void GPAllocator_Delete (void* memory) { +void default_allocator_free (void* memory) { if (memory == nullptr) return; Aligned_Free(memory); Remove_Allocation(memory); @@ -136,32 +137,32 @@ void GPAllocator_Delete (void* memory) { // printf("[GP] Deleting memory %p\n", memory); } -Allocator GPAllocator () { - return { GPAllocator_Proc, nullptr }; +Allocator default_allocator () { + return { default_allocator_proc, nullptr }; } -void* GPAllocator_Proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data) { +void* default_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data) { u16 alignment = 16; // default alignment Thread_Context* context = thread_context(); - if (context) alignment = context->GPAllocator_alignment; + if (context) alignment = context->default_allocator_alignment; switch (mode) { case Allocator_Mode::ALLOCATE: { - return GPAllocator_New(requested_size, alignment); + return default_allocator_new(requested_size, alignment); } break; case Allocator_Mode::RESIZE: { - void* result = GPAllocator_Resize(old_size, old_memory, requested_size, alignment); + void* result = default_allocator_realloc(old_size, old_memory, requested_size, alignment); // NOTE: The _aligned_realloc function already copies the old memory, so there's // no need to copy the old memory block here. return result; } break; case Allocator_Mode::DEALLOCATE: { - GPAllocator_Delete(old_memory); // unused + default_allocator_free(old_memory); // unused } break; case Allocator_Mode::DETAILS: { Assert(allocator_data == nullptr); - return "GPAllocator"; + return "default_allocator"; } break; } diff --git a/lib/Base/General_Purpose_Allocator.h b/lib/Base/General_Purpose_Allocator.h index 0d763b4..37c1ef4 100644 --- a/lib/Base/General_Purpose_Allocator.h +++ b/lib/Base/General_Purpose_Allocator.h @@ -38,17 +38,18 @@ struct General_Allocator { General_Allocator* get_general_allocator_data(); -constexpr u16 GPAllocator_Default_Alignment = 16; +constexpr u16 default_allocator_Default_Alignment = 16; -Allocator GPAllocator (); +Allocator default_allocator (); -void* GPAllocator_Proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data); +void* default_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data); -void* GPAllocator_New (s64 new_size, s64 alignment=16, bool initialize=true); -void* GPAllocator_Resize (s64 old_size, void* old_memory, s64 new_size, s64 alignment=16, bool initialize=true); -void GPAllocator_Delete (void* memory); +void* default_allocator_new (s64 new_size, s64 alignment=16, bool initialize=true); +void* default_allocator_realloc (s64 old_size, void* old_memory, s64 new_size, s64 alignment=16, bool initialize=true); +void default_allocator_free (void* memory); -bool GPAllocator_Is_This_Yours (void* old_memory); -void GPAllocator_Initialize_Allocation_Tracker (); -bool GPAllocator_Tracking_Enabled (); +bool default_allocator_Is_This_Yours (void* old_memory); +void default_allocator_Initialize_Allocation_Tracker (); +bool default_allocator_Tracking_Enabled (); +// #TODO: I want to be able to tag any allocations in debug mode. \ No newline at end of file diff --git a/lib/Base/Logger.cpp b/lib/Base/Logger.cpp index abb9bca..a4e1393 100644 --- a/lib/Base/Logger.cpp +++ b/lib/Base/Logger.cpp @@ -29,4 +29,4 @@ void print (string message) { void print_error (string error_message) { Logger* logger = context_logger(); logger->proc(error_message, Log_Level::Error, logger->data); -} \ No newline at end of file +} diff --git a/lib/Base/String.cpp b/lib/Base/String.cpp index d64da72..ab45329 100644 --- a/lib/Base/String.cpp +++ b/lib/Base/String.cpp @@ -33,6 +33,21 @@ string copy_string (string s) { return str; } +string copy_string_no_context (string s) { + if (s.count <= 0) + return ""; + string str = {}; + + str.count = s.count; + str.data = (u8*)default_allocator_new(s.count + 1); + + memcpy(str.data, s.data, s.count); + + str.data[str.count] = '\0'; // null-terminate for backwards compatibility? + + return str; +} + string copy_string (char* c_string) { string str = {}; s64 string_length = strlen(c_string); @@ -171,7 +186,7 @@ string format_string_no_context (char* format, ...) { string str = {}; - str.data = (u8*)GPAllocator_New(BUFFER_SIZE); + str.data = (u8*)default_allocator_new(BUFFER_SIZE); va_list args; va_start(args, format); @@ -267,7 +282,7 @@ internal force_inline void reset_string_builder (String_Builder* sb, bool keep_m force_inline string builder_to_string (String_Builder* sb) { string final_string = copy_string(to_string(to_view(*sb))); - free_string_builder(sb); + // reset_string_builder(sb, false); // maybe this shouldn't be here! Too magical... return final_string; } diff --git a/lib/Base/String.h b/lib/Base/String.h index 0215be3..d1dae81 100644 --- a/lib/Base/String.h +++ b/lib/Base/String.h @@ -77,6 +77,7 @@ bool is_valid (string s); bool is_c_string (string s); u8* to_c_string (string s); // #allocates string copy_string (string s); // #allocates, returned string is #null-terminated. +string copy_string_no_context (string s); string copy_string (char* c_string); // #allocates, returned string is #null-terminated. string to_string (ArrayView str); ArrayView to_view (string s); @@ -112,23 +113,3 @@ string trim_right (string s, string chars=DEFAULT_SPACES, bool replace_with_zero // Need an API for inserting various types (ints, floats, etc.) into a String_Builder, and advancing // the count. -// #string_builder -// #limitations This won't be as fast as Jon's String_Builder in jai because we're backing it with an -// Arena, which requires a variable number of cycles depending on if our process has -// memory available already. It also has a max capacity depending on what Arena_Reserve we choose. -// That being said, the implementation is much simpler. -typedef ArenaArray String_Builder; // struct String_Builder - -force_inline String_Builder* new_string_builder (Arena_Reserve new_reserve=Arena_Reserve::Size_64K); -force_inline void append (String_Builder* sb, string s); -void append (String_Builder* sb, ArrayView strings); -// This should probably be called append_but_do_not_increment_count -internal force_inline void append_no_add (String_Builder* sb, string s); // for appending null terminators, does not increment count. -void print_to_builder (String_Builder* sb, string format, ...); -void print_to_builder_internal (String_Builder* sb, string format, va_list args); -string string_view (String_Builder* sb); -internal force_inline void reset_string_builder (String_Builder* sb, bool keep_memory=false); - -// #rename copy_string_and_free_builder -force_inline string builder_to_string (String_Builder* sb); // returns copy and frees string_builder -internal force_inline void free_string_builder (String_Builder* sb); diff --git a/lib/Base/String_Builder.h b/lib/Base/String_Builder.h new file mode 100644 index 0000000..f0d657f --- /dev/null +++ b/lib/Base/String_Builder.h @@ -0,0 +1,26 @@ +// #string_builder +// #limitations This won't be as fast as Jon's String_Builder in jai because we're backing it with an +// Arena, which calls VirtualAlloc, which is much slower than just using stack space to start. +// It also has a max capacity depending on what Arena_Reserve we choose. +// That being said, the implementation is much simpler, and we can keep it around for a bit. +// We can make it a lot faster by always having a string builder available in the thread_context, +// and just fetching that when we need it. + +typedef ArenaArray String_Builder; // struct String_Builder + + +force_inline String_Builder* new_string_builder (Arena_Reserve new_reserve=Arena_Reserve::Size_64K); +force_inline void append (String_Builder* sb, string s); +void append (String_Builder* sb, ArrayView strings); +// This should probably be called append_but_do_not_increment_count +internal force_inline void append_no_add (String_Builder* sb, string s); // for appending null terminators, does not increment count. +void print_to_builder (String_Builder* sb, string format, ...); +void print_to_builder_internal (String_Builder* sb, string format, va_list args); +string string_view (String_Builder* sb); +internal force_inline void reset_string_builder (String_Builder* sb, bool keep_memory=false); + +// #rename copy_string_and_free_builder +force_inline string builder_to_string (String_Builder* sb); // returns copy and frees string_builder +internal force_inline void free_string_builder (String_Builder* sb); + + diff --git a/lib/Base/Timing.h b/lib/Base/Timing.h index 43d44a6..209d2ce 100644 --- a/lib/Base/Timing.h +++ b/lib/Base/Timing.h @@ -79,6 +79,10 @@ string format_bytes (s64 bytes, s32 trailing_width = 3) { unit_index += 1; } + // This makes the trailing width param kinda pointless... idk. + if (unit_index == 0) trailing_width = 0; + // if (unit_index == 1) trailing_width = 2; + switch (trailing_width) { case 0: return format_string("%.0f %s", count_f64, units[unit_index].data); case 1: return format_string("%.1f %s", count_f64, units[unit_index].data); diff --git a/lib/Base/run_tests.cpp b/lib/Base/run_tests.cpp index 95301c3..99b440e 100644 --- a/lib/Base/run_tests.cpp +++ b/lib/Base/run_tests.cpp @@ -19,7 +19,9 @@ void run_post_setup_tests() { // String builder example: // OK. I can work with this. - auto sb = new_string_builder(Arena_Reserve::Size_64K); + String_Builder* sb = context_builder(); + reset_string_builder(sb, true); + append(sb, "string_literal_example"); append(sb, " "); print_to_builder(sb, "There are %d cats in the %s", 64, "house.\n"); @@ -45,11 +47,11 @@ void run_post_setup_tests() { log("Done. Success: %d\n", success); // push_allocator(allocator(thread_context()->arena)); - push_allocator(GPAllocator()); + push_allocator(default_allocator()); string file_path = "D:/Work/OpenBCI/ToolZ/prototyping-gui-main/modules/native-proto-lib/native-sdk-prototyping/src/SignalProcessing.cpp"; - ArrayView file_data = read_entire_file(file_path, true); + ArrayView file_data = read_entire_file(file_path, true, true); log("file_data: \n"); - log("%s\n", file_data.data); + log("%s\n", file_data.data); // #note this is not null-terminated } { // Test hashing: u64 start = 0x512585; diff --git a/lib/Graphics.cpp b/lib/Graphics.cpp index 490d70f..b6d5206 100644 --- a/lib/Graphics.cpp +++ b/lib/Graphics.cpp @@ -56,7 +56,7 @@ Graphics* graphics_thread_init () { Assert(context != nullptr); - push_allocator(GPAllocator()); + push_allocator(default_allocator()); if (context->graphics == nullptr) { context->graphics = New(true); diff --git a/lib/OS/OS_Filesystem.cpp b/lib/OS/OS_Filesystem.cpp index a33f838..5085869 100644 --- a/lib/OS/OS_Filesystem.cpp +++ b/lib/OS/OS_Filesystem.cpp @@ -84,8 +84,8 @@ string get_full_path (string drive_label, Dense_FS* dfs, s32 first_parent_index, array_add(path_list_reverse, drive_letter_with_colon); - // reset_string_builder(sb, true); - String_Builder* sb = new_string_builder(); + String_Builder* sb = context_builder(); + reset_string_builder(sb, true); for (s64 i = path_list_reverse.count-1; i >= 0; i -= 1) { append(sb, path_list_reverse[i]); diff --git a/lib/OS/OS_Win32.cpp b/lib/OS/OS_Win32.cpp index 52e1726..702243b 100644 --- a/lib/OS/OS_Win32.cpp +++ b/lib/OS/OS_Win32.cpp @@ -59,7 +59,7 @@ struct OS_System_Info { // #Monitors b32 monitors_enumerated; - Array monitors; // Back with GPAllocator + Array monitors; // Back with default_allocator // #Drives Table drives; // should we just store ptrs to OS_Drive? I think so.. @@ -136,7 +136,13 @@ internal LONG WINAPI Win32_Exception_Filter (EXCEPTION_POINTERS* exception_ptrs) for (;;) Sleep(1000); } + // #TODO: Runtime assertion failed? + // #Exception handling code (TODO) + if (thread_context()->stack_trace) { + os_write_string_unsynchronized("\n[Win32_Exception_Filter] Stack Trace\n", true); + print_stack_trace(); + } ExitProcess(1); @@ -144,7 +150,10 @@ internal LONG WINAPI Win32_Exception_Filter (EXCEPTION_POINTERS* exception_ptrs) } // internal void Main_Entry_Point (int argc, WCHAR **argv); -internal void Win32_Entry_Point (int argc, WCHAR **argv) { +internal void Win32_Entry_Point (int argc, WCHAR **argv) { stack_trace(); + os_write_string_unsynchronized("Fatal Error!\n\nStack trace: ", true); + print_stack_trace(); + // Timed_Block_Print("Win32_Entry_Point"); // See: w32_entry_point_caller(); (raddebugger) SetUnhandledExceptionFilter(&Win32_Exception_Filter); @@ -226,7 +235,7 @@ internal void Win32_Entry_Point (int argc, WCHAR **argv) { } { OS_System_Info* info = &global_win32_state.system_info; - info->monitors.allocator = GPAllocator(); + info->monitors.allocator = default_allocator(); u8 buffer[MAX_COMPUTERNAME_LENGTH + 1] = {0}; DWORD size = MAX_COMPUTERNAME_LENGTH + 1; if(GetComputerNameA((char*)buffer, &size)) { @@ -236,7 +245,7 @@ internal void Win32_Entry_Point (int argc, WCHAR **argv) { } { OS_Process_Info* info = &global_win32_state.process_info; - info->windows.allocator = GPAllocator(); + info->windows.allocator = default_allocator(); DWORD length = GetCurrentDirectoryW(0, 0); // This can be freed later when we call temp_reset(); u16* memory = NewArray(temp(), length + 1); @@ -247,7 +256,7 @@ internal void Win32_Entry_Point (int argc, WCHAR **argv) { // Setup event arena, allocators for Array<> types. if (!global_win32_state.process_info.event_arena) { - global_win32_state.process_info.event_arena = next_arena(Arena_Reserve::Size_64K); + global_win32_state.process_info.event_arena = bootstrap_arena(Arena_Reserve::Size_64K); } // [ ] Get Working directory (info->working_path) @@ -282,20 +291,21 @@ internal bool thread_init (Thread* thread, Thread_Proc proc, string thread_name) s64 this_thread_index = InterlockedIncrement(&next_thread_index); // 2. #NewContext Setup NEW thread local context - ExpandableArena* arena_ex = expandable_arena_new(Arena_Reserve::Size_64M, 16); + ExpandableArena* arena_ex = bootstrap_expandable_arena(Arena_Reserve::Size_64M); push_arena(arena_ex); // #NOTE: we don't assign thread_local_context until we hit the #thread_entry_point thread->context = New(); - thread->context->temp = expandable_arena_new(Arena_Reserve::Size_2M, 16); - thread->context->arena = arena_ex; - thread->context->allocator = allocator(arena_ex); - thread->context->thread_idx = (s32)this_thread_index; + thread->context->temp = bootstrap_expandable_arena(Arena_Reserve::Size_2M); + thread->context->arena = arena_ex; + thread->context->allocator = allocator(arena_ex); + thread->context->thread_idx = (s32)this_thread_index; // #NOTE: This will disappear once the thread is de-initted. If we want this string, copy it! - thread->context->thread_name = copy_string(thread_name); - thread->context->log_builder = new_string_builder(Arena_Reserve::Size_64M); - thread->context->error_arena = next_arena(Arena_Reserve::Size_64M); - thread->context->logger = {default_logger_proc, &default_logger}; + thread->context->thread_name = copy_string(thread_name); + thread->context->log_builder = new_string_builder(Arena_Reserve::Size_64M); + thread->context->string_builder = new_string_builder(Arena_Reserve::Size_2M); + thread->context->error_arena = bootstrap_arena(Arena_Reserve::Size_64M); + thread->context->logger = {default_logger_proc, &default_logger}; thread->context->parent_thread_context = thread_context(); @@ -322,7 +332,7 @@ internal void thread_deinit (Thread* thread,bool zero_thread) { array_reset(*thread->context->log_builder); free_string_builder(thread->context->log_builder); - release_arena(thread->context->error_arena); + arena_delete(thread->context->error_arena); arena_delete(thread->context->temp); arena_delete(thread->context->arena); // must come last because thread->context is allocated with this arena! @@ -548,7 +558,7 @@ internal bool file_set_position (File file, s64 position) { return (bool)SetFilePointerEx(file.handle, position_li, nullptr, FILE_BEGIN); } -internal ArrayView read_entire_file (File file) { +ArrayView read_entire_file (File file, bool add_null_terminator) { ArrayView file_data; bool result = file_length(file, &file_data.count); @@ -556,7 +566,13 @@ internal ArrayView read_entire_file (File file) { result = file_set_position(file, 0); if (!result) return {}; - file_data.data = NewArray(file_data.count, false); + s64 total_file_size = file_data.count; + + if (add_null_terminator) { + total_file_size += 1; + } + + file_data.data = NewArray(total_file_size, false); if (file_data.data == nullptr) return {}; s64 bytes_read = 0; @@ -566,17 +582,21 @@ internal ArrayView read_entire_file (File file) { return {}; } + if (add_null_terminator) { + file_data[total_file_size-1] = 0; + } + Assert(bytes_read == file_data.count); file_data.count = bytes_read; return file_data; } -internal ArrayView read_entire_file (string file_path, bool log_errors) { +internal ArrayView read_entire_file (string file_path, bool add_null_terminator, bool log_errors) { File f = file_open(file_path, false, false, log_errors); if (!file_is_valid(f)) return {}; - ArrayView file_data = read_entire_file(f); + ArrayView file_data = read_entire_file(f, add_null_terminator); file_close(&f); @@ -1009,11 +1029,11 @@ s32 os_cpu_secondary_core_count () { // #Drives constexpr u64 Win32_Max_Path_Length = 260; bool Win32_Discover_Drives () { - push_allocator(GPAllocator()); + push_allocator(default_allocator()); // Initialize drive_table if necessary. Table* drive_table = get_drive_table(); if (!drive_table->allocated) { - drive_table->allocator = GPAllocator(); + drive_table->allocator = default_allocator(); // #TODO(Low priority): #hash_table need a macro for initializing with string keys! drive_table->hash_function = string_hash_function_fnv1a; drive_table->compare_function = string_keys_match; @@ -1068,8 +1088,13 @@ bool Win32_Discover_Drives () { Win32_Max_Path_Length, &serial_number, &max_comp_len, &file_system_flags, (LPWSTR)file_system_name, Win32_Max_Path_Length)) { drive->label = drive_label; - drive->volume_name = wide_to_utf8(volume_name); - if (drive->volume_name == "") { drive->volume_name = copy_string("Local Disk"); } + if (volume_name[0] == 0) { + drive->volume_name = copy_string("Local Disk"); + } else { + drive->volume_name = wide_to_utf8(volume_name); + } + if (drive->volume_name == "") { drive->volume_name = copy_string("Local Disk"); } // Probably redundant?? + drive->type = (Win32_Drive_Type)drive_type; { push_allocator(temp()); drive->file_system = Win32_filesystem_from_string(wide_to_utf8(file_system_name)); @@ -1172,7 +1197,7 @@ struct ST_File_Enumeration { // global state global ST_File_Enumeration* stfe; void free_stfe_and_reset () { - push_allocator(GPAllocator()); + push_allocator(default_allocator()); array_free(stfe->drives); @@ -1337,7 +1362,7 @@ s64 win32_file_enum_thread_proc (Thread* thread) { } void os_run_file_enumeration_single_threaded () { - push_allocator(GPAllocator()); + push_allocator(default_allocator()); stfe = New(); (*stfe) = { @@ -1395,7 +1420,7 @@ bool Serialize_ST_File_Enumeration (string file_path) { bool Deserialize_ST_File_Enumeration (string file_path) { Timed_Block_Print("Deserialize_ST_File_Enumeration"); - push_allocator(GPAllocator()); + push_allocator(default_allocator()); if (!stfe) stfe = New(); (*stfe) = { {}, @@ -1407,7 +1432,7 @@ bool Deserialize_ST_File_Enumeration (string file_path) { push_allocator(temp()); auto_release_temp(); - Deserializer deserializer = read_entire_file(file_path, true); + Deserializer deserializer = read_entire_file(file_path, false, true); if (deserializer.count == 0) return false; auto d = &deserializer; diff --git a/lib/OS/OS_Win32.h b/lib/OS/OS_Win32.h index 7bc37fb..4616590 100644 --- a/lib/OS/OS_Win32.h +++ b/lib/OS/OS_Win32.h @@ -41,8 +41,8 @@ internal bool file_length (File file, s64* length); internal bool file_length (string file_path, s64* length); internal s64 file_current_position (File file); internal bool file_set_position (File file, s64 position); -internal ArrayView read_entire_file (File file); -internal ArrayView read_entire_file (string file_path, bool log_errors=false); +internal ArrayView read_entire_file (File file, bool add_null_terminator); +internal ArrayView read_entire_file (string file_path, bool add_null_terminator=false, bool log_errors=false); // use to_byte_view to convert ArrayView to ArrayView internal bool file_write (File* file, void* data, s64 length); diff --git a/lib/OS/OS_Win32_File_Enumeration.cpp b/lib/OS/OS_Win32_File_Enumeration.cpp index 1897674..e1567fe 100644 --- a/lib/OS/OS_Win32_File_Enumeration.cpp +++ b/lib/OS/OS_Win32_File_Enumeration.cpp @@ -20,7 +20,7 @@ struct File_Enumeration_Thread_Results { // #userdata }; void initialize (File_Enumeration_Thread_Results* fcr) { // Preallocate for 2^22 files: - fcr->arena = next_arena(Arena_Reserve::Size_2G); + fcr->arena = bootstrap_arena(Arena_Reserve::Size_2G); fcr->d_offsets = arena_array_new(4194304, Arena_Reserve::Size_2G); fcr->d_lengths = arena_array_new(4194304, Arena_Reserve::Size_2G); @@ -83,7 +83,7 @@ string path_from_parent_index (Thread_Group* group, Parent_Index pid, Parent_Ind // This is much stupider and more complicated than I would like, unfortunately. string directory_get_full_path (Thread_Group* group, Parent_Index pid, string dir_name) { - push_allocator(GPAllocator()); // to copy from String_Builder + push_allocator(default_allocator()); // to copy from String_Builder Array paths; paths.allocator = temp(); @@ -105,7 +105,9 @@ string directory_get_full_path (Thread_Group* group, Parent_Index pid, string di } // go in reverse order and add together string - String_Builder* sb = new_string_builder(Arena_Reserve::Size_64K); + String_Builder* sb = context_builder(); + reset_string_builder(sb, true); + for (s64 i = paths.count-1; i >= 0; i -= 1) { append(sb, paths[i]); append(sb, "\\"); @@ -165,7 +167,7 @@ Thread_Continue_Status file_enumeration_thread_group_proc (Thread_Group* group, // particular problem. This data can be rescued before we File_Enumeration_Thread_Results* results; if (!thread->context->userdata) { - thread->context->userdata = New(GPAllocator()); + thread->context->userdata = New(default_allocator()); initialize((File_Enumeration_Thread_Results*)thread->context->userdata); } results = (File_Enumeration_Thread_Results*)thread->context->userdata; @@ -220,7 +222,7 @@ Thread_Continue_Status file_enumeration_thread_group_proc (Thread_Group* group, add_record(results, &find_data, name, next_index, is_directory); if (is_directory) { - push_allocator(GPAllocator()); + push_allocator(default_allocator()); auto new_work = New(false); new_work->first_directory = directory_get_full_path(group, pi, name); new_work->parent = next_index; @@ -245,12 +247,12 @@ s64 multithreaded_file_enumeration_master_proc (Thread* thread) { s32 thread_count = os_cpu_physical_core_count(); - push_allocator(GPAllocator()); + push_allocator(default_allocator()); thread_group_init(file_enum_thread_group, thread_count, file_enumeration_thread_group_proc, true); for_each(d, task->drives) { - auto work = New(GPAllocator(), false); //replace with arena bootstrap? + auto work = New(default_allocator(), false); //replace with arena bootstrap? work->first_directory = task->drives[d]->label; // this includes the colon-slash, (e.g. `C:\`). work->parent = {-1, -1}; // #HACK: (s32)d work->is_root = true; diff --git a/lib/OS/OS_Win32_NTFS.cpp b/lib/OS/OS_Win32_NTFS.cpp index 7442f2d..b00dd4a 100644 --- a/lib/OS/OS_Win32_NTFS.cpp +++ b/lib/OS/OS_Win32_NTFS.cpp @@ -229,7 +229,7 @@ Error* NTFS_MFT_read_raw (OS_Drive* drive) { Assert(data_attribute != nullptr); // #dense_fs_alloc - drive->data = New(GPAllocator()); + drive->data = New(default_allocator()); initialize(drive->data, drive); NTFS_RunHeader* dataRun = (NTFS_RunHeader*)((u8*)data_attribute + data_attribute->dataRunsOffset); @@ -457,7 +457,7 @@ bool Deserialize_Win32_Drives (string file_path) { push_allocator(temp()); auto_release_temp(); - Deserializer deserializer = read_entire_file(file_path, true); + Deserializer deserializer = read_entire_file(file_path, false, true); if (deserializer.count == 0) return false; auto d = &deserializer; @@ -468,11 +468,11 @@ bool Deserialize_Win32_Drives (string file_path) { Assert(magic_number == Win32_Drive_Magic_Number); Read(d, &drive_count); - ntfs_workspace.arena = next_arena(Arena_Reserve::Size_64G); + ntfs_workspace.arena = bootstrap_arena(Arena_Reserve::Size_64G); push_arena(ntfs_workspace.arena); Assert(ntfs_workspace.drives.count == 0); array_resize(ntfs_workspace.supplementary, drive_count); - // ntfs_workspace.drives.allocator = GPAllocator(); + // ntfs_workspace.drives.allocator = default_allocator(); log("[Deserialize_Win32_Drives] drive_count: %d", drive_count); @@ -589,7 +589,7 @@ void ntfs_create_enumeration_threads (s32 thread_count) { if (!ex1_ntfs.initialized) { Timed_Block_Print("Thread initialization (ntfs)"); ex1_ntfs.initialized = true; ex1_ntfs.threads = ArrayView(thread_count); - ex1_ntfs.threads_in_flight.allocator = GPAllocator(); + ex1_ntfs.threads_in_flight.allocator = default_allocator(); for_each(t, ex1_ntfs.threads) { string thread_name = format_string("ntfs_enumeration_thread#%d", t); bool success = thread_init(&ex1_ntfs.threads[t], ntfs_enumeration_thread_proc, thread_name); @@ -665,7 +665,7 @@ void Ex1_show_ntfs_workspace () { using namespace ImGui; i, ex1_ntfs.threads[i].proc != nullptr, ex1_ntfs.threads[i].context != nullptr, ex1_ntfs.threads[i].data != nullptr); }*/ /*// #NTFS_MFT_RAW - push_allocator(GPAllocator()); + push_allocator(default_allocator()); Array> drive_split; drive_split.allocator = temp(); // this is only needed for this frame @@ -711,7 +711,7 @@ void Ex1_show_ntfs_workspace () { using namespace ImGui; ex1_ntfs.threads_started = true; for (s64 t = 0; t < active_thread_count; t += 1) { Thread* thread = &ex1_ntfs.threads[t]; - Arena* thread_arena = next_arena(Arena_Reserve::Size_64K); + Arena* thread_arena = bootstrap_arena(Arena_Reserve::Size_64K); push_arena(thread_arena); auto thread_data = New(); thread_data->pool = thread_arena; @@ -727,14 +727,14 @@ void Ex1_show_ntfs_workspace () { using namespace ImGui; for_each(t, ex1_ntfs.threads_in_flight) { if (thread_is_done(ex1_ntfs.threads_in_flight[t])) { - push_allocator(GPAllocator()); + push_allocator(default_allocator()); Thread* thread = ex1_ntfs.threads_in_flight[t]; auto task = thread_task(NTFS_Enumeration_Task); array_free(task->drives); // make sure to retreive any data you need to from here! - release_arena(task->pool); + arena_delete(task->pool); thread_deinit(ex1_ntfs.threads_in_flight[t], false); array_unordered_remove_by_index(ex1_ntfs.threads_in_flight, t); @@ -746,7 +746,7 @@ void Ex1_show_ntfs_workspace () { using namespace ImGui; /* #NTFS_MFT_RAW if (ex1_ntfs.threads_started && !ex1_ntfs.threads_in_flight.count) { // All threads are complete, we're free to clean up remaining memory - push_allocator(GPAllocator()); + push_allocator(default_allocator()); array_free(ex1_ntfs.threads); array_free(ex1_ntfs.threads_in_flight); diff --git a/lib/meta_generated.h b/lib/meta_generated.h deleted file mode 100644 index 700a5eb..0000000 --- a/lib/meta_generated.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -const char* MUSA_LIB_VERSION = "0.2"; -#define BUILD_DEBUG 1 -#define OS_WINDOWS 1 -#define OS_LINUX 0 -#define OS_MACOS 0 -#define OS_ANDROID 0 -#define OS_IOS 0 -#define ARCH_CPU_X64 1 -#define ARCH_CPU_ARM64 0 -#define OS_IS_UNIX 0 -#define COMPILER_MSVC 1 -#define COMPILER_CLANG 0 -#define ARRAY_ENABLE_BOUNDS_CHECKING 1 -#define COMPILER_GCC 0 diff --git a/lib_main.cpp b/lib_main.cpp index 0b2d8f6..482d9fa 100644 --- a/lib_main.cpp +++ b/lib_main.cpp @@ -10,14 +10,15 @@ // I'll see where it's used most often and see if I can make macros or templates to make // them easier to use. -#include "lib/meta_generated.h" +// #include "lib/meta_generated.h" #include "lib/Base/Base.h" #include "lib/Base/Allocator.h" #include "lib/Base/Array.h" #include "lib/Base/General_Purpose_Allocator.h" +#include "lib/Base/String.h" #include "lib/Base/Arena.h" #include "lib/Base/Arena_Array.h" -#include "lib/Base/String.h" +#include "lib/Base/String_Builder.h" #include "lib/Base/Hash_Functions.h" #include "lib/Base/Hash_Table.h" #include "lib/Base/Arena_Hash_Table.h" @@ -32,7 +33,7 @@ #include "lib/Base/Base_Thread_Context.h" #include "lib/Base/Expandable_Arena.h" #include "lib/Base/Timing.h" -#include "lib/Base/Arena_Free_List.cpp" +// #include "lib/Base/Arena_Free_List.cpp" #include "lib/Base/Arena.cpp" #include "lib/Base/String.cpp" diff --git a/src/Base_Entry_Point.cpp b/src/Base_Entry_Point.cpp index 3bd25ae..cd3b845 100644 --- a/src/Base_Entry_Point.cpp +++ b/src/Base_Entry_Point.cpp @@ -7,6 +7,7 @@ internal void Main_Entry_Point (int argc, WCHAR **argv); return 0; } #else + #pragma comment(linker, "/SUBSYSTEM:WINDOWS") #include // globals __argc, __wargv int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) { @@ -16,7 +17,7 @@ internal void Main_Entry_Point (int argc, WCHAR **argv); #endif #endif -internal void Main_Entry_Point (int argc, WCHAR **argv) { // #entry_point +internal void Main_Entry_Point (int argc, WCHAR **argv) { // #entry_point: Main + Context Setup // #TODO: Check if base frequency is even available. u32 base_frequency = (u32)CPU_Base_Frequency(); set_cpu_base_frequency(base_frequency); // REQUIRED FOR TIMING MODULE! will depend on CPU @@ -28,6 +29,8 @@ internal void Main_Entry_Point (int argc, WCHAR **argv) { // #entry_point // before setting up the thread context! Bootstrap_Main_Thread_Context(); + stack_trace(); // #stack_trace: #entry_point (first stack trace) + #if OS_WINDOWS Win32_Entry_Point(argc, argv); #endif @@ -37,7 +40,7 @@ internal void Main_Entry_Point (int argc, WCHAR **argv) { // #entry_point #if BASE_RUN_TESTS run_post_setup_tests(); #endif -#if BUILD_EXPLORER_APP_WIN32 // #entry_point +#if BUILD_EXPLORER_APP_WIN32 // #entry_point: Custom program Explorer_ImGui_Application_Win32(); // #rename #endif #if BUILD_CUSTOM_GUI diff --git a/src/Ex1.cpp b/src/Ex1.cpp index a2a0c0e..2d0c05c 100644 --- a/src/Ex1.cpp +++ b/src/Ex1.cpp @@ -50,6 +50,9 @@ bool Ex1_Register_Global_Hotkeys () { global Key_Combination program_exit_hotkey { ImGuiKey_W, USE_CTRL, USE_SHIFT, KEY_UNUSED, TRIGGER_ONCE }; global Key_Combination program_minimize_hotkey { ImGuiKey_W, USE_CTRL, KEY_UNUSED, KEY_UNUSED, TRIGGER_ONCE }; +global Key_Combination decrease_font_size_hotkey { ImGuiKey_Minus, USE_CTRL, KEY_UNUSED, KEY_UNUSED, TRIGGER_ONCE }; +global Key_Combination increase_font_size_hotkey { ImGuiKey_Equal, USE_CTRL, KEY_UNUSED, KEY_UNUSED, TRIGGER_ONCE }; + bool Ex1_check_key_combinations() { update_global_keyboard_state(); // #program_hotkeys @@ -59,6 +62,12 @@ bool Ex1_check_key_combinations() { if (check_key_combination(&program_minimize_hotkey)) { Win32_Minimize_Window_To_Tray(get_main_window_pointer()); } + if (check_key_combination(&decrease_font_size_hotkey)) { // see ImGui_Show_Font_Info. + imgui_default_font.current_size = clamp(imgui_default_font.current_size - 1, 0, 5); + } + if (check_key_combination(&increase_font_size_hotkey)) { + imgui_default_font.current_size = clamp(imgui_default_font.current_size + 1, 0, 5); + } // #Ex1_hotkeys return false; } @@ -73,7 +82,8 @@ struct Ex1_Workspace { RadixSort dir_modtime_radix; bool sort_completed; - // Reordered strings: + // Reordered strings: #note: these are NOT required to save in memory, better to search and + // sort the filtered strings using the solved radices ArrayView files_sorted_by_size; ArrayView files_sorted_by_modtime; }; @@ -82,7 +92,7 @@ global Ex1_Workspace ex1w; void free_ex1_workspace_and_reset () { if (ex1w.sort_completed) { - push_allocator(GPAllocator()); + push_allocator(default_allocator()); radix_sort_free(&ex1w.file_size_radix); radix_sort_free(&ex1w.file_modtime_radix); @@ -112,7 +122,7 @@ void Ex1_show_enumeration_workspace () { using namespace ImGui; push_imgui_window("Enumerated Data Workspace"); if (!ex1w.sort_completed) { - push_allocator(GPAllocator()); + push_allocator(default_allocator()); Timed_Block_Print("radix_sort_u64: file sizes, file modtimes, directory modtimes"); ArrayView sizes = to_view(*stfe->files.sizes); radix_sort_u64(&ex1w.file_size_radix, sizes.data, (u32)sizes.count); @@ -186,13 +196,12 @@ void Ex1_Control_Panel () { using namespace ImGui; push_allocator(temp()); ArrayView drives = os_get_available_drives(); // only includes drives that are ready. - - if (!USN_Journal_Monitoring_Ready(drives[0]) && Button("Enable USN Monitoring for all drives")) { - Win32_Enable_USN_Journal_Monitoring(drives); - } - if (USN_Journal_Monitoring_Ready(drives[0]) && Button("Query USN Journal")) { - Query_USN_Journal(drives); - } + // if (!USN_Journal_Monitoring_Ready(drives[0]) && Button("Enable USN Monitoring for all drives")) { + // Win32_Enable_USN_Journal_Monitoring(drives); + // } + // if (USN_Journal_Monitoring_Ready(drives[0]) && Button("Query USN Journal")) { + // Query_USN_Journal(drives); + // } if (!all_drives_enumerated) { // Text("drive_table is valid: %d", table_is_valid(drive_table)); @@ -225,8 +234,8 @@ void Ex1_Control_Panel () { using namespace ImGui; // bool all_drives_enumerated = !ex1_ntfs.threads_in_flight.count // && (drives_enumerated == drives.count); - // string file_path = format_string_temp("%s_DriveData.bin", os_get_machine_name().data); - string file_path = "D:/Projects/Cpp/Musa-Cpp-Lib-V2/bin/MUSA-PC3_DriveData.bin";// FIXED path. + string file_path = format_string_temp("D:/TempSync/Filesystem_Data/%s_DriveData.bin", os_get_machine_name().data); + // string file_path = "D:/TempSync/Filesystem_Data/MUSA-PC3_DriveData.bin"; Text("fixed file_path: %s", file_path.data); if (!all_drives_enumerated && file_exists(file_path)) { // #autoload Deserialize_ST_File_Enumeration(file_path); @@ -238,7 +247,7 @@ void Ex1_Control_Panel () { using namespace ImGui; // if (file_enum_multithreading_started()) { // if (thread_is_done(drive_enumeration->master_thread)) { - // push_allocator(GPAllocator()); + // push_allocator(default_allocator()); // // Thread* thread = drive_enumeration->master_thread; // // auto task = thread_task(Drive_Enumeration); // // Nothing to free? @@ -304,37 +313,33 @@ void ImGui_Debug_Panel () { using namespace ImGui; Begin("Debug Panel"); // #cpuid Text("[cpus] physical: %d, logical: %d, primary: %d, secondary: %d", os_cpu_physical_core_count(), os_cpu_logical_core_count(), os_cpu_primary_core_count(), os_cpu_secondary_core_count()); - { SeparatorText("Arena In-Use List"); - lock_guard(&arena_free_list->mutex); - for (u8 i = 0; i < Arena_Reserve_Count; i += 1) { - #if ARENA_DEBUG - auto t = format_cstring( - " [%s] in_use: %d, committed_bytes: %s", - format_bytes(Arena_Sizes[i], 0).data, - arena_free_list->in_flight_count[i], - format_bytes(committed_bytes(arena_free_list->in_flight[i])).data - ); - #else - auto t = format_cstring( - " [%s] in_use: %d, committed_bytes: %s", - format_bytes(Arena_Sizes[i], 0).data, - arena_free_list->in_flight_count[i], - "disabled in release mode" - ); - #endif - Text(t); - } - SeparatorText("Arena Free List"); - for (u8 i = 0; i < Arena_Reserve_Count; i += 1) { - auto t = format_cstring( - " [%s] free: %d, committed_bytes: %s", - format_bytes(Arena_Sizes[i], 0).data, - (s32)arena_free_list->free_table[i].count, - format_bytes(committed_bytes(arena_free_list->free_table[i])).data - ); - Text(t); +#if BUILD_DEBUG + SeparatorText("Default Allocator Allocations"); + { lock_guard(&allocator_mutex); + // Replace this with two sliders min and max to filter allocations? + Checkbox("Show small allocations (<1kB)", &default_allocator_show_small_allocations); + auto allocations = to_view(get_general_allocator_data()->allocations); + Text("%s in %lld allocations", + format_bytes(get_general_allocator_data()->total_bytes_allocated).data, + allocations.count); + for_each(a, allocations) { + if (!default_allocator_show_small_allocations && allocations[a].size < 1024) { + continue; + } + Text(" [%lld] ptr: %p (size: %s, alignment: %d)", + a, allocations[a].memory, format_bytes(allocations[a].size).data, allocations[a].alignment); } } + SeparatorText("Arenas in Use"); + { lock_guard(&arenas_in_use_mutex); + Assert(arenas_in_use.allocated > 0); + for_each(a, arenas_in_use) { + auto arena = arenas_in_use[a]; + if (!is_valid(arena)) continue; + Text("[%d], source %s:%d (%s)", a, arena->file_path.data, arena->line_number, arena->function_name.data); + } + } +#endif // BUILD_DEBUG SeparatorText("Child Threads"); SeparatorText("Errors"); ArrayView errors = get_all_errors(thread_context()); diff --git a/src/String_Analysis.cpp b/src/String_Analysis.cpp index f61b923..ce4f43d 100644 --- a/src/String_Analysis.cpp +++ b/src/String_Analysis.cpp @@ -39,7 +39,7 @@ void count_unique_chars_from_string (string s) { } void count_unique_utf8_chars () { Timed_Block_Print("count_unique_utf8_chars"); - unique_codepoints_utf32.allocator = GPAllocator(); + unique_codepoints_utf32.allocator = default_allocator(); Assert(stfe != nullptr); for (s64 i = 0; i < stfe->dirs.offsets->count; i += 1) { diff --git a/src/explorer_main.cpp b/src/explorer_main.cpp index 5e0d0fa..757bf8b 100644 --- a/src/explorer_main.cpp +++ b/src/explorer_main.cpp @@ -83,7 +83,7 @@ void Explorer_ImGui_Application_Win32 () { string font_file_name = "RobotoMono-Regular.ttf"; - imgui_default_font.sizes.allocator = GPAllocator(); + imgui_default_font.sizes.allocator = default_allocator(); imgui_default_font.font_name = font_file_name; for (s64 i = 0; i < ArrayCount(imgui_font_sizes); i += 1) { @@ -151,7 +151,7 @@ void Explorer_ImGui_Application_Win32 () { ImGui_Debug_Panel(); Ex1_Control_Panel(); - ImGui_Show_Font_Info(); + // ImGui_Show_Font_Info(); ImGui_Pop_Default_Font();