diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f2e906..e4fe106 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,9 @@ SET (CMAKE_VERBOSE_MAKEFILE ON) if (MSVC) # Suppress warning: C++ exception handler used, but unwind semantics are not enabled. add_compile_options(/wd4530) + add_compile_options(-D_CRT_SECURE_NO_WARNINGS) + add_compile_options(-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING) + add_compile_options(-D_CRT_NONSTDC_NO_DEPRECATE) endif() SET (EXE_NAME "mexplore_v2") @@ -29,12 +32,41 @@ SET (SRC_FILES lib/third_party/dear-imgui/imgui_impl_dx11.cpp lib/third_party/dear-imgui/imgui_impl_win32.cpp - exe_main.cpp + #lib_main + lib/Base/Base.cpp + lib/Base/Allocator.cpp + lib/Base/General_Purpose_Allocator.cpp + #lib/Base/Base_Thread_Context.cpp + #lib/Base/Arena.cpp + #lib/Base/String.cpp + #lib/Base/ErrorType.cpp + #lib/Base/Logger.cpp + #lib/Base/Expandable_Arena.cpp + #lib/Base/Threads.cpp + #lib/OS/OS_Filesystem.cpp + #lib/Base/Thread_Group.cpp + #lib/Base/Unicode.cpp + #lib/Base/RadixSort.cpp + lib/OS/OS_Win32.cpp + + #lib/Base/run_tests.cpp + + #exe_main + #src/ImGui_Supplementary.cpp + #src/String_Analysis.cpp + #src/explorer_main.cpp + #src/Base_Entry_Point.cpp + + # Not in main project: for future opengl backend + #lib/Graphics.cpp ) SET (INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/lib + ${PROJECT_SOURCE_DIR}/lib/Base + ${PROJECT_SOURCE_DIR}/lib/OS + ${PROJECT_SOURCE_DIR}/lib/UI ${PROJECT_SOURCE_DIR}/lib/third_party ) @@ -49,6 +81,7 @@ endif() SET (SYSTEM_LIBRARIES ) -add_executable(${EXE_NAME} ${SRC_FILES}) +#add_executable(${EXE_NAME} ${SRC_FILES}) +add_library(${EXE_NAME} STATIC ${SRC_FILES}) target_include_directories(${EXE_NAME} PRIVATE ${INCLUDE_DIRS}) target_link_libraries(${EXE_NAME} PRIVATE ${LINK_LIBS_DIRS} ${SYSTEM_LIBRARIES}) diff --git a/lib/Base/Allocator.cpp b/lib/Base/Allocator.cpp index b986c9a..00fcd8d 100644 --- a/lib/Base/Allocator.cpp +++ b/lib/Base/Allocator.cpp @@ -1,3 +1,6 @@ +#include "Allocator.h" +#include "Base_Thread_Context.h" + void* internal_alloc (s64 size) { Allocator allocator = context_allocator(); void* result = allocator.proc(Allocator_Mode::ALLOCATE, size, 0, nullptr, allocator.data); @@ -16,9 +19,4 @@ void internal_free (void* memory) { allocator.proc(Allocator_Mode::DEALLOCATE, 0, 0, memory, allocator.data); } -void print_context_allocator () { - Assert(thread_context()->allocator.proc); - char* result = (char*)thread_context()->allocator.proc(Allocator_Mode::DETAILS, 0, 0, nullptr, thread_context()->allocator.data); - log_none("Current allocator details: %s", result); -} diff --git a/lib/Base/Allocator.h b/lib/Base/Allocator.h index bc17bf3..33d566b 100644 --- a/lib/Base/Allocator.h +++ b/lib/Base/Allocator.h @@ -1,5 +1,7 @@ #pragma once +#include "Base.h" + #define ALLOCATOR_DEBUG_MODE 1 #define ALLOCATOR_POISON_MEMORY_ON_ALLOCATION \ (BUILD_DEBUG && ALLOCATOR_DEBUG_MODE) @@ -120,6 +122,4 @@ template T* copy_struct (T* src) { memcpy(dst, src, sizeof(T)); } -// #TODO: Turn this into a macro that also provides the -// file, line number to the print. -void print_context_allocator (); \ No newline at end of file + diff --git a/lib/Base/Arena.cpp b/lib/Base/Arena.cpp index fa57883..6780383 100644 --- a/lib/Base/Arena.cpp +++ b/lib/Base/Arena.cpp @@ -309,4 +309,115 @@ void* fixed_arena_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 o } return nullptr; -} \ No newline at end of file +} + +// #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 + +#include "Base.h" + +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.h b/lib/Base/Arena.h index dcbd3d2..b952fae 100644 --- a/lib/Base/Arena.h +++ b/lib/Base/Arena.h @@ -1,5 +1,9 @@ #pragma once +#include "Base.h" +#include "Array.h" +#include "Allocator.h" + struct ExpandableArena; // fwd declare #temp #if OS_WINDOWS diff --git a/lib/Base/Arena_Array.h b/lib/Base/Arena_Array.h index a1755ce..11ef351 100644 --- a/lib/Base/Arena_Array.h +++ b/lib/Base/Arena_Array.h @@ -1,5 +1,7 @@ #pragma once +#include "Arena.h" + constexpr s64 ARRAY_ARENA_START_OFFSET = 64; template 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/Array.h b/lib/Base/Array.h index 4d4b34c..4124171 100644 --- a/lib/Base/Array.h +++ b/lib/Base/Array.h @@ -1,6 +1,8 @@ // Strongly influenced by Array.jai in Basic module. #pragma once +#include "Allocator.h" + // For Arena-Backed arrays use ArenaArray MSVC_RUNTIME_CHECKS_OFF diff --git a/lib/Base/Base.cpp b/lib/Base/Base.cpp new file mode 100644 index 0000000..191cb33 --- /dev/null +++ b/lib/Base/Base.cpp @@ -0,0 +1,22 @@ +#include "Base.h" +// #TEMPORARY +// #include "Allocator.h" +// #include "Array.h" +// #include "General_Purpose_Allocator.h" +// #include "Arena.h" +// #include "Arena_Array.h" +// #include "MString.h" +// #include "Hash_Functions.h" +// #include "Hash_Table.h" +// #include "Arena_Hash_Table.h" +#if OS_WINDOWS +// # include "OS_Win32.h" +#endif +// #include "Layout.h" +// #include "Logger.h" + +// #include "Serializer.h" + +// #include "Base_Thread_Context.h" +// #include "Expandable_Arena.h" +// #include "Timing.h" \ No newline at end of file diff --git a/lib/Base/Base.h b/lib/Base/Base.h index 3ad4cf9..87af53a 100644 --- a/lib/Base/Base.h +++ b/lib/Base/Base.h @@ -408,67 +408,6 @@ template T clamp (T v, T min, T max) { return x; } -// #thread_primitives #move? -#if OS_WINDOWS - struct Condition_Variable { - CONDITION_VARIABLE condition_variable; - }; - struct Semaphore { - HANDLE event; - }; - struct Mutex { - CRITICAL_SECTION csection; - }; - struct OS_Thread { - HANDLE windows_thread; - s32 windows_thread_id; - }; - struct File { - HANDLE handle; - }; - internal void mutex_init (Mutex* mutex); - internal void mutex_destroy (Mutex* mutex); - internal void lock (Mutex* mutex); - internal void unlock (Mutex* mutex); -#endif -#define POSIX_THREADS OS_LINUX || OS_MACOS || OS_IOS || OS_ANDROID -#if OS_MACOS - struct Semaphore { - task_t owner; - semaphore_t event = 0; - }; -#endif -#if OS_LINUX || OS_ANDROID - struct Semaphore { - sem_t semaphore; - }; -#endif -#if OS_IS_UNIX // #posix threads - struct OS_Thread { - pthread_t thread_handle; - Semaphore is_alive; - Semaphore suspended; - b32 is_done; - }; -#endif - - -#define lock_guard(x) \ - Mutex_Lock_Guard Concat(_auto_lock_guard_, __LINE__)(x) - -struct Mutex_Lock_Guard { - Mutex* mutex; - - Mutex_Lock_Guard (Mutex* mutex) { - this->mutex = mutex; - lock(mutex); - } - - ~Mutex_Lock_Guard () { - unlock(mutex); - } -}; - // Helper macros for raw arrays: #define ArrayCount(array) sizeof(array) / sizeof(array[0]) // For-loop construct macros diff --git a/lib/Base/Base_Thread_Context.cpp b/lib/Base/Base_Thread_Context.cpp index 5fda429..a485925 100644 --- a/lib/Base/Base_Thread_Context.cpp +++ b/lib/Base/Base_Thread_Context.cpp @@ -1,4 +1,5 @@ // See Context_Base in jai, and TCTX in raddebugger: +#include "Base_Thread_Context.h" internal void Bootstrap_Main_Thread_Context () { // Timed_Block_Print_No_Context("Bootstrap_Main_Thread_Context"); diff --git a/lib/Base/Base_Thread_Context.h b/lib/Base/Base_Thread_Context.h index 2290b5a..9a4a715 100644 --- a/lib/Base/Base_Thread_Context.h +++ b/lib/Base/Base_Thread_Context.h @@ -1,31 +1,37 @@ -// #hacky fwd declares -struct Error; -struct Graphics; +#pragma once + +#include "Base.h" +#include "General_Purpose_Allocator.h" +// #include "Arena.h" +// #include "Logger.h" +#include "MString.h" +// #include "Threads.h" +// #include "Expandable_Arena.h" struct Thread_Context { - ExpandableArena* temp; // Used for temporary allocations, scratch space. - ExpandableArena* arena; // general purpose local arena + // ExpandableArena* temp; // Used for temporary allocations, scratch space. + // ExpandableArena* arena; // general purpose local arena Allocator allocator; s32 thread_idx; // u16 _padding0; u16 GPAllocator_alignment = 16; - Logger logger = {nullptr, nullptr}; - String_Builder* log_builder; + // Logger logger = {nullptr, nullptr}; + // String_Builder* log_builder; // Stack_Trace* stack_trace; - Array child_threads; // maybe should be linked-list? + // 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(); - Error* first_error = nullptr; - Error* current_error = nullptr; - Arena* error_arena; + // Error* first_error = nullptr; + // Error* current_error = nullptr; + // Arena* error_arena; // Graphics stuff: - Graphics* graphics; + // Graphics* graphics; void* userdata; // for appending other arenas, etc. }; @@ -53,3 +59,13 @@ struct Push_Allocator { } }; +// #TODO: Turn this into a macro that also provides the +// file, line number to the print. +void print_context_allocator (); + +// void print_context_allocator () { +// Assert(thread_context()->allocator.proc); + +// char* result = (char*)thread_context()->allocator.proc(Allocator_Mode::DETAILS, 0, 0, nullptr, thread_context()->allocator.data); +// log_none("Current allocator details: %s", result); +// } diff --git a/lib/Base/General_Purpose_Allocator.cpp b/lib/Base/General_Purpose_Allocator.cpp index e5fa7c5..26cab1b 100644 --- a/lib/Base/General_Purpose_Allocator.cpp +++ b/lib/Base/General_Purpose_Allocator.cpp @@ -1,3 +1,7 @@ +#include "General_Purpose_Allocator.h" +#include "Base_Thread_Context.h" +#include "Threads.h" + #if GP_ALLOCATOR_TRACK_ALLOCATIONS global General_Allocator gAllocator; // @Shared global Mutex allocator_mutex; diff --git a/lib/Base/General_Purpose_Allocator.h b/lib/Base/General_Purpose_Allocator.h index 0d763b4..35df813 100644 --- a/lib/Base/General_Purpose_Allocator.h +++ b/lib/Base/General_Purpose_Allocator.h @@ -1,5 +1,9 @@ #pragma once +#include "Base.h" +#include "Allocator.h" +#include "Array.h" + #define GP_ALLOCATOR_TRACK_ALLOCATIONS BUILD_DEBUG #define GP_ALLOCATOR_VERY_DEBUG BUILD_DEBUG && 0 @@ -21,6 +25,7 @@ #define Aligned_Realloc(old_sz, ptr, sz, align) gp_aligned_realloc(old_sz, ptr, sz, align) #define Aligned_Free(ptr) std::free(ptr) #endif + struct Allocation { s64 size; void* memory; diff --git a/lib/Base/Hash_Functions.h b/lib/Base/Hash_Functions.h index 13bef54..eb2c0a1 100644 --- a/lib/Base/Hash_Functions.h +++ b/lib/Base/Hash_Functions.h @@ -1,3 +1,5 @@ +#include "MString.h" + constexpr u32 HASH_INIT = 5381; u32 sdbm_hash (void* data, s64 size) { u32 h = HASH_INIT; diff --git a/lib/Base/String.h b/lib/Base/MString.h similarity index 98% rename from lib/Base/String.h rename to lib/Base/MString.h index 0215be3..fba0bf4 100644 --- a/lib/Base/String.h +++ b/lib/Base/MString.h @@ -1,4 +1,9 @@ #pragma once + +#include "Base.h" +#include "Array.h" +#include "Arena_Array.h" + // #TODO: #strings: // [ ] see: #Parsing stuff: // [?] How do I accept variadic arguments of any type to my print function? diff --git a/lib/Base/String.cpp b/lib/Base/String.cpp index d64da72..c464e9d 100644 --- a/lib/Base/String.cpp +++ b/lib/Base/String.cpp @@ -1,3 +1,5 @@ +#include "MString.h" + // #NOTE: All string building, printing and copying operations SHOULD null-terminate the // strings for backwards compatibility reasons. #FIX if something doesn't follow this rule! bool is_valid (string s) { diff --git a/lib/Base/Threads.h b/lib/Base/Threads.h new file mode 100644 index 0000000..efc1cb9 --- /dev/null +++ b/lib/Base/Threads.h @@ -0,0 +1,62 @@ +#pragma once + +// #thread_primitives #move? +#if OS_WINDOWS + struct Condition_Variable { + CONDITION_VARIABLE condition_variable; + }; + struct Semaphore { + HANDLE event; + }; + struct Mutex { + CRITICAL_SECTION csection; + }; + struct OS_Thread { + HANDLE windows_thread; + s32 windows_thread_id; + }; + struct File { + HANDLE handle; + }; +#endif +#define POSIX_THREADS OS_LINUX || OS_MACOS || OS_IOS || OS_ANDROID +#if OS_MACOS + struct Semaphore { + task_t owner; + semaphore_t event = 0; + }; +#endif +#if OS_LINUX || OS_ANDROID + struct Semaphore { + sem_t semaphore; + }; +#endif +#if OS_IS_UNIX // #posix threads + struct OS_Thread { + pthread_t thread_handle; + Semaphore is_alive; + Semaphore suspended; + b32 is_done; + }; +#endif + +internal void mutex_init (Mutex* mutex); +internal void mutex_destroy (Mutex* mutex); +internal void lock (Mutex* mutex); +internal void unlock (Mutex* mutex); + +#define lock_guard(x) \ + Mutex_Lock_Guard Concat(_auto_lock_guard_, __LINE__)(x) + +struct Mutex_Lock_Guard { + Mutex* mutex; + + Mutex_Lock_Guard (Mutex* mutex) { + this->mutex = mutex; + lock(mutex); + } + + ~Mutex_Lock_Guard () { + unlock(mutex); + } +}; diff --git a/lib/Base/Timing.h b/lib/Base/Timing.h index 43d44a6..09db5dc 100644 --- a/lib/Base/Timing.h +++ b/lib/Base/Timing.h @@ -1,3 +1,6 @@ +#pragma once +#include "Base.h" + // #Timing API: #define System_Timed_Block_Print(name) \ system_timed_block_print Concat(_sys_timed_block_print_guard, __LINE__)(name) diff --git a/lib/OS/OS_Win32.cpp b/lib/OS/OS_Win32.cpp index 52e1726..ab1eaa3 100644 --- a/lib/OS/OS_Win32.cpp +++ b/lib/OS/OS_Win32.cpp @@ -5,6 +5,8 @@ // before terminating. // Or we can move child threads up to the parent? +#include "OS_Win32.h" + constexpr s64 FILETIME_TO_UNIX = 116444736000000000i64; f64 GetUnixTimestamp () { FILETIME fileTime; diff --git a/lib/OS/OS_Win32.h b/lib/OS/OS_Win32.h index 7bc37fb..d55a31b 100644 --- a/lib/OS/OS_Win32.h +++ b/lib/OS/OS_Win32.h @@ -1,6 +1,15 @@ +#pragma once + +#include "Base.h" +#include "Array.h" +#include "Threads.h" + #pragma comment(lib, "user32") #pragma comment(lib, "shell32") #include +#include +#include +#include f64 GetUnixTimestamp (); s64 GetUnixTimestampNanoseconds (); diff --git a/lib_main.cpp b/lib_main.cpp index 818e281..1ac5488 100644 --- a/lib_main.cpp +++ b/lib_main.cpp @@ -49,7 +49,6 @@ // OS-Abstraction Layer #include "lib/Base/Threads.cpp" #include "lib/OS/OS_Filesystem.cpp" - #include "lib/Base/Thread_Group.cpp" #if OS_WINDOWS diff --git a/src/Base_Entry_Point.cpp b/src/Base_Entry_Point.cpp index 3bd25ae..00cce08 100644 --- a/src/Base_Entry_Point.cpp +++ b/src/Base_Entry_Point.cpp @@ -1,3 +1,6 @@ +#include "Base_Entry_Point.h" +#include "Timing.h" + internal void Main_Entry_Point (int argc, WCHAR **argv); #if OS_WINDOWS diff --git a/src/Ex1.cpp b/src/Ex1.cpp deleted file mode 100644 index a2a0c0e..0000000 --- a/src/Ex1.cpp +++ /dev/null @@ -1,361 +0,0 @@ -struct ExplorerUI { - // u8 search_input[64]; - // u8 secondary_input[64]; -}; - -struct Explorer { - // A bunch of flags? - // Icon cache? - // Array frame_textures; -}; - -struct Ex1_NTFS_Enumeration { - b32 initialized; - b32 threads_started; - - ArrayView threads; - Array threads_in_flight; -}; - -// #Ex1_global_state -global ExplorerUI explorer_ui; -global Explorer explorer; -global Ex1_NTFS_Enumeration ex1_ntfs; - -#define HOTKEY_ID_BRING_TO_FOREGROUND 1 -#define VK_SPACE_KEY_CODE 0x20 -// #define HOTKEY_ID_HIDE_TITLEBAR - -void Ex1_Unregister_Global_Hotkeys () { - UnregisterHotKey(nullptr, HOTKEY_ID_BRING_TO_FOREGROUND); -} - -bool Ex1_Register_Global_Hotkeys () { - if (!RegisterHotKey(nullptr, HOTKEY_ID_BRING_TO_FOREGROUND, MOD_CONTROL|MOD_SHIFT|MOD_ALT, VK_SPACE_KEY_CODE)) { - Assert(false); - log_error("Failed to register global hotkey Ctrl-Shift-Alt-Space"); - return false; - } - return true; -} - -#define USE_CTRL true -#define USE_SHIFT true -#define USE_ALT true -#define TRIGGER_ONCE true -#define TRIGGER_EVERY_FRAME false -#define KEY_UNUSED false - -// #program_hotkeys (Not specific to Ex1) -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 }; - -bool Ex1_check_key_combinations() { - update_global_keyboard_state(); - // #program_hotkeys - if (check_key_combination(&program_exit_hotkey)) { - return true; - } - if (check_key_combination(&program_minimize_hotkey)) { - Win32_Minimize_Window_To_Tray(get_main_window_pointer()); - } - // #Ex1_hotkeys - return false; -} - -// #Workspaces are FOR DEVELOPMENT ONLY. -struct Ex1_Workspace { - s32 path_select; - s32 file_select; - - RadixSort file_size_radix; - RadixSort file_modtime_radix; - RadixSort dir_modtime_radix; - bool sort_completed; - - // Reordered strings: - ArrayView files_sorted_by_size; - ArrayView files_sorted_by_modtime; -}; - -global Ex1_Workspace ex1w; - -void free_ex1_workspace_and_reset () { - if (ex1w.sort_completed) { - push_allocator(GPAllocator()); - - radix_sort_free(&ex1w.file_size_radix); - radix_sort_free(&ex1w.file_modtime_radix); - radix_sort_free(&ex1w.dir_modtime_radix); - - array_free(ex1w.files_sorted_by_size); - array_free(ex1w.files_sorted_by_modtime); - - zero_struct(&ex1w); - } -} - -// #TODO: Move all sort stuff to OS_Win32? -// Make a general version of this that takes two ArrayView and reorders. -// There's no need to do this until we have the filtered results. -void os_win32_reorder_files_by_radix (RadixSort* r, ArrayView* files, bool reverse_order=false) { - Timed_Block_Print("os_win32_reorder_files_by_radix"); - // Where are my source files!? - (*files) = ArrayView(r->ranks.count); - for_each(f, (*files)) { - // (*files)[f] = get_file_copy(stfe, r->ranks[f]); - (*files)[f] = get_file_string_view(stfe, r->ranks[f]); - } -} - -void Ex1_show_enumeration_workspace () { using namespace ImGui; - push_imgui_window("Enumerated Data Workspace"); - - if (!ex1w.sort_completed) { - push_allocator(GPAllocator()); - 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); - ArrayView file_modtimes = to_view(*stfe->files.modtimes); - radix_sort_u64(&ex1w.file_modtime_radix, file_modtimes.data, (u32)file_modtimes.count); - ArrayView dirs_modtimes = to_view(*stfe->dirs.modtimes); - radix_sort_u64(&ex1w.dir_modtime_radix, dirs_modtimes.data, (u32)dirs_modtimes.count); - // Create ArrayView, ArrayView sizes, and ArrayView modtimes - os_win32_reorder_files_by_radix(&ex1w.file_size_radix, &ex1w.files_sorted_by_size); - os_win32_reorder_files_by_radix(&ex1w.file_modtime_radix, &ex1w.files_sorted_by_modtime); - // reordering by the rank permutations generated by RadixSort. - ex1w.sort_completed = true; - } - - if (!ex1w.sort_completed) { return; } - - SeparatorText("Files ordered by modtime"); - s32 file_count = (s32)ex1w.files_sorted_by_modtime.count; - SliderInt("Select file index", &ex1w.file_select, 0, file_count-1); - string file_name = copy_string(ex1w.files_sorted_by_modtime[ex1w.file_select]); - Text("%s", file_name.data); - u32 radix_index = rank(&ex1w.file_modtime_radix, ex1w.file_select); - Text("date modified: %s", format_time_datetime(get_file_modtime(stfe, radix_index)).data); - - SeparatorText("Files ordered by size"); - file_count = (s32)ex1w.files_sorted_by_size.count; - // SliderInt("Select file index", &ex1w.file_select, 0, file_count-1); - file_name = copy_string(ex1w.files_sorted_by_size[ex1w.file_select]); - Text("%s", file_name.data); - radix_index = rank(&ex1w.file_size_radix, ex1w.file_select); - Text("size: %s", format_bytes(get_file_size_bytes(stfe, radix_index)).data); - // Text("date modified: %s", format_time_datetime(get_file_modtime(stfe, radix_index)).data); - - if (Button("Count unique UTF-8 characters")) { - count_unique_utf8_chars(); - } - - Text("unique_codepoints_utf32.count: %", unique_codepoints_utf32.count); - - for_each(u, unique_codepoints_utf32) { - Text("[%d] Code point as hex: 0x%X", u, unique_codepoints_utf32[u]); - } - - Text("files_sorted_by_size size in bytes: %lld", ex1w.files_sorted_by_size.count * sizeof(string)); - Text("files_sorted_by_modtime size in bytes: %lld", ex1w.files_sorted_by_modtime.count * sizeof(string)); - - for (s64 i = 1; i < 128; i += 1) { - u8 cstring[2] = {}; - cstring[0] = (u8)i; - cstring[1] = 0; - Text("codepoint[0x%X]: %s, count: %lld", i, cstring, count_ascii_codepoints[i]); - } -} - -void Ex1_Control_Panel () { using namespace ImGui; - f64 frame_time = GetUnixTimestamp(); - Table* drive_table = get_drive_table(); - - push_imgui_window("Control Panel"); - - // if (Button("Debug break")) { debug_break(); } - if (/*Button("Discover drives") ||*/!table_is_valid(drive_table)) { Win32_Discover_Drives(); } - - // Text("ntfs_workspace_files_loaded: %s", ntfs_workspace_files_loaded()? "true": "false"); - // if (ntfs_workspace_files_loaded()) { - // Ex1_show_ntfs_workspace(); - // return; - // } - - bool all_drives_enumerated = stfe && stfe->thread_completed; - 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 (!all_drives_enumerated) { - // Text("drive_table is valid: %d", table_is_valid(drive_table)); - for_each(i, drives) { - OS_Drive* drive = drives[i]; - - Text(" > [%d] drive letter: %s (is_present: %d)", i + 1, drive->label.data, drive->is_present); - if (drive->time_to_enumerate != 0) { - SameLine(); - Text("Enumerated in %.2f seconds", drive->time_to_enumerate); - } - // SameLine(); - // if (Button(format_cstring("Read NTFS MFT Raw##%s", drive->label.data))) { - // push_arena(thread_context()->arena); - // Error* error = NTFS_MFT_read_raw(drive); - // } - } - } - - s32 drives_enumerated = 0; - for_each(d, drives) { - OS_Drive* drive = drives[d]; - if (!drives[d]->time_to_enumerate) { continue; } - if (!drives[d]->data) { continue; } - - if (drives[d]->data->paths.offsets->count > 0) { - drives_enumerated += 1; - } - } - // 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. - Text("fixed file_path: %s", file_path.data); - if (!all_drives_enumerated && file_exists(file_path)) { // #autoload - Deserialize_ST_File_Enumeration(file_path); - } - if (drives.count > 0 && !all_drives_enumerated && file_exists(file_path) && Button("Load from file (this machine)")) { - Deserialize_ST_File_Enumeration(file_path); - // Deserialize_Win32_Drives(file_path); - } - - // if (file_enum_multithreading_started()) { - // if (thread_is_done(drive_enumeration->master_thread)) { - // push_allocator(GPAllocator()); - // // Thread* thread = drive_enumeration->master_thread; - // // auto task = thread_task(Drive_Enumeration); - // // Nothing to free? - // thread_deinit(drive_enumeration->master_thread, true); - // } - // } - - // #FileEnumerationST - if (stfe && stfe->thread_started) { - // print dirs enumerated, etc - if (!stfe->thread_completed) Text("Enumeration Thread Active (elapsed: %s)", format_time_seconds(frame_time-stfe->start_time).data); - if (stfe->dirs.offsets) { - s64 dirs_enumerated = stfe->dirs.offsets->count; - Text("Dirs enumerated: %lld", dirs_enumerated); - // if (!stfe->thread_completed) Text("Current dir: %s", get_last_path_copy(stfe).data); - } - if (stfe->files.offsets) { - s64 files_enumerated = stfe->files.offsets->count; - Text("Files enumerated: %lld", files_enumerated); - // if (!stfe->thread_completed) Text("Current file: %s", get_last_file_copy(stfe).data); - } - - if (stfe->thread_completed) { - Text("String bytes stored: %s", format_bytes(stfe->dirs.strings->count + stfe->files.strings->count).data); - Text("Elapsed time: %s", format_time_seconds(stfe->end_time-stfe->start_time).data); - } - } - if (stfe && stfe->thread_started && !stfe->thread_completed) { - Assert(stfe->master_thread != nullptr); - if (thread_is_done(stfe->master_thread)) { - thread_deinit(stfe->master_thread, true); - stfe->thread_completed = true; - } - } - - if (all_drives_enumerated && Button("Save enumerated data")) { - if (!Serialize_ST_File_Enumeration(file_path)) { - log_error("Failed to write enumerated files"); - os_log_error(); - } - } - - if (all_drives_enumerated && Button("Reset State")) { - free_ex1_workspace_and_reset(); - free_stfe_and_reset(); - return; - } - - if (all_drives_enumerated) { - Ex1_show_enumeration_workspace(); - } - - if (drives.count > 0 && !all_drives_enumerated && Button("Enumerate all NTFS drives")) { // && ex1_ntfs.initialized - os_run_file_enumeration_single_threaded(); - // os_run_file_enumeration_multithreaded(); // #disabled for now - return; - } -} - -void ImGui_Debug_Panel () { using namespace ImGui; - push_allocator(temp()); - - 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); - } - } - SeparatorText("Child Threads"); - SeparatorText("Errors"); - ArrayView errors = get_all_errors(thread_context()); - if (errors.count && Button("Clear all errors")) { - clear_errors(thread_context()); - errors.count = 0; - } - for_each(e, errors) { - auto button_label = format_cstring("Clear##%d", e); - if (Button(button_label)) { - clear_error(thread_context(), errors[e]); - continue; - } - SameLine(); - Text(" [%d] %s", e, to_string(errors[e]).data); - } - Spacing(); - if (Button("Push some error")) { - log_warning("This is a warning."); - log_error("... and this is an error."); - } - - End(); -} \ No newline at end of file diff --git a/src/explorer_main.cpp b/src/explorer_main.cpp index 5e0d0fa..3233ecc 100644 --- a/src/explorer_main.cpp +++ b/src/explorer_main.cpp @@ -1,4 +1,366 @@ -#include "Ex1.cpp" +// #include " + +struct ExplorerUI { + // u8 search_input[64]; + // u8 secondary_input[64]; +}; + +struct Explorer { + // A bunch of flags? + // Icon cache? + // Array frame_textures; +}; + +struct Ex1_NTFS_Enumeration { + b32 initialized; + b32 threads_started; + + ArrayView threads; + Array threads_in_flight; +}; + +// #Ex1_global_state +global ExplorerUI explorer_ui; +global Explorer explorer; +global Ex1_NTFS_Enumeration ex1_ntfs; + +#define HOTKEY_ID_BRING_TO_FOREGROUND 1 +#define VK_SPACE_KEY_CODE 0x20 +// #define HOTKEY_ID_HIDE_TITLEBAR + +void Ex1_Unregister_Global_Hotkeys () { + UnregisterHotKey(nullptr, HOTKEY_ID_BRING_TO_FOREGROUND); +} + +bool Ex1_Register_Global_Hotkeys () { + if (!RegisterHotKey(nullptr, HOTKEY_ID_BRING_TO_FOREGROUND, MOD_CONTROL|MOD_SHIFT|MOD_ALT, VK_SPACE_KEY_CODE)) { + Assert(false); + log_error("Failed to register global hotkey Ctrl-Shift-Alt-Space"); + return false; + } + return true; +} + +#define USE_CTRL true +#define USE_SHIFT true +#define USE_ALT true +#define TRIGGER_ONCE true +#define TRIGGER_EVERY_FRAME false +#define KEY_UNUSED false + +// #program_hotkeys (Not specific to Ex1) +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 }; + +bool Ex1_check_key_combinations() { + update_global_keyboard_state(); + // #program_hotkeys + if (check_key_combination(&program_exit_hotkey)) { + return true; + } + if (check_key_combination(&program_minimize_hotkey)) { + Win32_Minimize_Window_To_Tray(get_main_window_pointer()); + } + // #Ex1_hotkeys + return false; +} + +// #Workspaces are FOR DEVELOPMENT ONLY. +struct Ex1_Workspace { + s32 path_select; + s32 file_select; + + RadixSort file_size_radix; + RadixSort file_modtime_radix; + RadixSort dir_modtime_radix; + bool sort_completed; + + // Reordered strings: + ArrayView files_sorted_by_size; + ArrayView files_sorted_by_modtime; +}; + +global Ex1_Workspace ex1w; + +void free_ex1_workspace_and_reset () { + if (ex1w.sort_completed) { + push_allocator(GPAllocator()); + + radix_sort_free(&ex1w.file_size_radix); + radix_sort_free(&ex1w.file_modtime_radix); + radix_sort_free(&ex1w.dir_modtime_radix); + + array_free(ex1w.files_sorted_by_size); + array_free(ex1w.files_sorted_by_modtime); + + zero_struct(&ex1w); + } +} + +// #TODO: Move all sort stuff to OS_Win32? +// Make a general version of this that takes two ArrayView and reorders. +// There's no need to do this until we have the filtered results. +void os_win32_reorder_files_by_radix (RadixSort* r, ArrayView* files, bool reverse_order=false) { + Timed_Block_Print("os_win32_reorder_files_by_radix"); + // Where are my source files!? + (*files) = ArrayView(r->ranks.count); + for_each(f, (*files)) { + // (*files)[f] = get_file_copy(stfe, r->ranks[f]); + (*files)[f] = get_file_string_view(stfe, r->ranks[f]); + } +} + +void Ex1_show_enumeration_workspace () { using namespace ImGui; + push_imgui_window("Enumerated Data Workspace"); + + if (!ex1w.sort_completed) { + push_allocator(GPAllocator()); + 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); + ArrayView file_modtimes = to_view(*stfe->files.modtimes); + radix_sort_u64(&ex1w.file_modtime_radix, file_modtimes.data, (u32)file_modtimes.count); + ArrayView dirs_modtimes = to_view(*stfe->dirs.modtimes); + radix_sort_u64(&ex1w.dir_modtime_radix, dirs_modtimes.data, (u32)dirs_modtimes.count); + // Create ArrayView, ArrayView sizes, and ArrayView modtimes + os_win32_reorder_files_by_radix(&ex1w.file_size_radix, &ex1w.files_sorted_by_size); + os_win32_reorder_files_by_radix(&ex1w.file_modtime_radix, &ex1w.files_sorted_by_modtime); + // reordering by the rank permutations generated by RadixSort. + ex1w.sort_completed = true; + } + + if (!ex1w.sort_completed) { return; } + + SeparatorText("Files ordered by modtime"); + s32 file_count = (s32)ex1w.files_sorted_by_modtime.count; + SliderInt("Select file index", &ex1w.file_select, 0, file_count-1); + string file_name = copy_string(ex1w.files_sorted_by_modtime[ex1w.file_select]); + Text("%s", file_name.data); + u32 radix_index = rank(&ex1w.file_modtime_radix, ex1w.file_select); + Text("date modified: %s", format_time_datetime(get_file_modtime(stfe, radix_index)).data); + + SeparatorText("Files ordered by size"); + file_count = (s32)ex1w.files_sorted_by_size.count; + // SliderInt("Select file index", &ex1w.file_select, 0, file_count-1); + file_name = copy_string(ex1w.files_sorted_by_size[ex1w.file_select]); + Text("%s", file_name.data); + radix_index = rank(&ex1w.file_size_radix, ex1w.file_select); + Text("size: %s", format_bytes(get_file_size_bytes(stfe, radix_index)).data); + // Text("date modified: %s", format_time_datetime(get_file_modtime(stfe, radix_index)).data); + + if (Button("Count unique UTF-8 characters")) { + count_unique_utf8_chars(); + } + + Text("unique_codepoints_utf32.count: %", unique_codepoints_utf32.count); + + for_each(u, unique_codepoints_utf32) { + Text("[%d] Code point as hex: 0x%X", u, unique_codepoints_utf32[u]); + } + + Text("files_sorted_by_size size in bytes: %lld", ex1w.files_sorted_by_size.count * sizeof(string)); + Text("files_sorted_by_modtime size in bytes: %lld", ex1w.files_sorted_by_modtime.count * sizeof(string)); + + for (s64 i = 1; i < 128; i += 1) { + u8 cstring[2] = {}; + cstring[0] = (u8)i; + cstring[1] = 0; + Text("codepoint[0x%X]: %s, count: %lld", i, cstring, count_ascii_codepoints[i]); + } +} + +void Ex1_Control_Panel () { using namespace ImGui; + f64 frame_time = GetUnixTimestamp(); + Table* drive_table = get_drive_table(); + + push_imgui_window("Control Panel"); + + // if (Button("Debug break")) { debug_break(); } + if (/*Button("Discover drives") ||*/!table_is_valid(drive_table)) { Win32_Discover_Drives(); } + + // Text("ntfs_workspace_files_loaded: %s", ntfs_workspace_files_loaded()? "true": "false"); + // if (ntfs_workspace_files_loaded()) { + // Ex1_show_ntfs_workspace(); + // return; + // } + + bool all_drives_enumerated = stfe && stfe->thread_completed; + 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 (!all_drives_enumerated) { + // Text("drive_table is valid: %d", table_is_valid(drive_table)); + for_each(i, drives) { + OS_Drive* drive = drives[i]; + + Text(" > [%d] drive letter: %s (is_present: %d)", i + 1, drive->label.data, drive->is_present); + if (drive->time_to_enumerate != 0) { + SameLine(); + Text("Enumerated in %.2f seconds", drive->time_to_enumerate); + } + // SameLine(); + // if (Button(format_cstring("Read NTFS MFT Raw##%s", drive->label.data))) { + // push_arena(thread_context()->arena); + // Error* error = NTFS_MFT_read_raw(drive); + // } + } + } + + s32 drives_enumerated = 0; + for_each(d, drives) { + OS_Drive* drive = drives[d]; + if (!drives[d]->time_to_enumerate) { continue; } + if (!drives[d]->data) { continue; } + + if (drives[d]->data->paths.offsets->count > 0) { + drives_enumerated += 1; + } + } + // 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. + Text("fixed file_path: %s", file_path.data); + if (!all_drives_enumerated && file_exists(file_path)) { // #autoload + Deserialize_ST_File_Enumeration(file_path); + } + if (drives.count > 0 && !all_drives_enumerated && file_exists(file_path) && Button("Load from file (this machine)")) { + Deserialize_ST_File_Enumeration(file_path); + // Deserialize_Win32_Drives(file_path); + } + + // if (file_enum_multithreading_started()) { + // if (thread_is_done(drive_enumeration->master_thread)) { + // push_allocator(GPAllocator()); + // // Thread* thread = drive_enumeration->master_thread; + // // auto task = thread_task(Drive_Enumeration); + // // Nothing to free? + // thread_deinit(drive_enumeration->master_thread, true); + // } + // } + + // #FileEnumerationST + if (stfe && stfe->thread_started) { + // print dirs enumerated, etc + if (!stfe->thread_completed) Text("Enumeration Thread Active (elapsed: %s)", format_time_seconds(frame_time-stfe->start_time).data); + if (stfe->dirs.offsets) { + s64 dirs_enumerated = stfe->dirs.offsets->count; + Text("Dirs enumerated: %lld", dirs_enumerated); + // if (!stfe->thread_completed) Text("Current dir: %s", get_last_path_copy(stfe).data); + } + if (stfe->files.offsets) { + s64 files_enumerated = stfe->files.offsets->count; + Text("Files enumerated: %lld", files_enumerated); + // if (!stfe->thread_completed) Text("Current file: %s", get_last_file_copy(stfe).data); + } + + if (stfe->thread_completed) { + Text("String bytes stored: %s", format_bytes(stfe->dirs.strings->count + stfe->files.strings->count).data); + Text("Elapsed time: %s", format_time_seconds(stfe->end_time-stfe->start_time).data); + } + } + if (stfe && stfe->thread_started && !stfe->thread_completed) { + Assert(stfe->master_thread != nullptr); + if (thread_is_done(stfe->master_thread)) { + thread_deinit(stfe->master_thread, true); + stfe->thread_completed = true; + } + } + + if (all_drives_enumerated && Button("Save enumerated data")) { + if (!Serialize_ST_File_Enumeration(file_path)) { + log_error("Failed to write enumerated files"); + os_log_error(); + } + } + + if (all_drives_enumerated && Button("Reset State")) { + free_ex1_workspace_and_reset(); + free_stfe_and_reset(); + return; + } + + if (all_drives_enumerated) { + Ex1_show_enumeration_workspace(); + } + + if (drives.count > 0 && !all_drives_enumerated && Button("Enumerate all NTFS drives")) { // && ex1_ntfs.initialized + os_run_file_enumeration_single_threaded(); + // os_run_file_enumeration_multithreaded(); // #disabled for now + return; + } +} + +void ImGui_Debug_Panel () { using namespace ImGui; + push_allocator(temp()); + + 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); + } + } + SeparatorText("Child Threads"); + SeparatorText("Errors"); + ArrayView errors = get_all_errors(thread_context()); + if (errors.count && Button("Clear all errors")) { + clear_errors(thread_context()); + errors.count = 0; + } + for_each(e, errors) { + auto button_label = format_cstring("Clear##%d", e); + if (Button(button_label)) { + clear_error(thread_context(), errors[e]); + continue; + } + SameLine(); + Text(" [%d] %s", e, to_string(errors[e]).data); + } + Spacing(); + if (Button("Push some error")) { + log_warning("This is a warning."); + log_error("... and this is an error."); + } + + End(); +} void Explorer_ImGui_Application_Win32 () { { // :Win32_Initialize_Extended