From 43bc710dbd0a8db0ea0556e1c04e70e7a76764b6 Mon Sep 17 00:00:00 2001 From: Doyle Date: Sun, 2 Sep 2018 21:17:14 +1000 Subject: [PATCH] Simplify memstack api --- DqnMemStack.cpp | 124 ++++++++-------- DqnUnitTest.cpp | 29 ++-- DqnVHashTable.cpp | 4 +- dqn.h | 362 +++++++++++++++------------------------------- dqn.natvis | 26 ++-- 5 files changed, 208 insertions(+), 337 deletions(-) diff --git a/DqnMemStack.cpp b/DqnMemStack.cpp index 0f93b6f..9f5cb86 100644 --- a/DqnMemStack.cpp +++ b/DqnMemStack.cpp @@ -5,7 +5,7 @@ FILE_SCOPE void DqnMemStack_Test() // Check Alignment if (1) { - auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); i32 const ALIGN64 = 64; i32 const ALIGN16 = 16; @@ -45,7 +45,7 @@ FILE_SCOPE void DqnMemStack_Test() // Check Non-Expandable if (1) { - auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::NonExpandable); + auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::NonExpandable); auto *result1 = stack.Push(DQN_MEGABYTE(2)); DQN_ASSERT(result1 == nullptr); DQN_ASSERT(stack.block->prev_block == nullptr); @@ -57,7 +57,7 @@ FILE_SCOPE void DqnMemStack_Test() // Check Expansion if (1) { - auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes); + auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes); DQN_ASSERT(stack.tracker.bounds_guard_size == 0); auto *old_block = stack.block; @@ -82,31 +82,31 @@ FILE_SCOPE void DqnMemStack_Test() // Check temporary regions if (1) { - auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); - DqnMemStack::Block *blockToReturnTo = stack.block; - auto headBefore = blockToReturnTo->head; - auto tail_before = blockToReturnTo->tail; + DqnMemStack::Block *block_to_return_to = stack.block; + auto head_before = block_to_return_to->head; + auto tail_before = block_to_return_to->tail; if (1) { - auto memGuard1 = stack.TempRegionGuard(); + auto mem_guard1 = stack.MemRegionScope(); auto *result2 = stack.Push(100); auto *result3 = stack.Push(100); auto *result4 = stack.Push(100); DQN_ASSERT(result2 && result3 && result4); - DQN_ASSERT(stack.block->head != headBefore); + DQN_ASSERT(stack.block->head != head_before); DQN_ASSERT(stack.block->tail == tail_before); - DQN_ASSERT(stack.block->memory == blockToReturnTo->memory); + DQN_ASSERT(stack.block->memory == block_to_return_to->memory); // Force allocation of new block auto *result5 = stack.Push(DQN_MEGABYTE(5)); DQN_ASSERT(result5); - DQN_ASSERT(stack.block != blockToReturnTo); - DQN_ASSERT(stack.tmp_region_count == 1); + DQN_ASSERT(stack.block != block_to_return_to); + DQN_ASSERT(stack.mem_region_count == 1); } - DQN_ASSERT(stack.block == blockToReturnTo); - DQN_ASSERT(stack.block->head == headBefore); + DQN_ASSERT(stack.block == block_to_return_to); + DQN_ASSERT(stack.block->head == head_before); DQN_ASSERT(stack.block->tail == tail_before); stack.Free(); @@ -115,32 +115,32 @@ FILE_SCOPE void DqnMemStack_Test() // Check temporary regions keep state if (1) { - auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); - DqnMemStack::Block *blockToReturnTo = stack.block; - auto headBefore = blockToReturnTo->head; - auto tail_before = blockToReturnTo->tail; + auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); + DqnMemStack::Block *block_to_return_to = stack.block; + auto head_before = block_to_return_to->head; + auto tail_before = block_to_return_to->tail; if (1) { - auto memGuard1 = stack.TempRegionGuard(); + auto mem_guard1 = stack.MemRegionScope(); auto *result2 = stack.Push(100); auto *result3 = stack.Push(100); auto *result4 = stack.Push(100); DQN_ASSERT(result2 && result3 && result4); - DQN_ASSERT(stack.block->head != headBefore); + DQN_ASSERT(stack.block->head != head_before); DQN_ASSERT(stack.block->tail == tail_before); - DQN_ASSERT(stack.block->memory == blockToReturnTo->memory); + DQN_ASSERT(stack.block->memory == block_to_return_to->memory); // Force allocation of new block auto *result5 = stack.Push(DQN_MEGABYTE(5)); DQN_ASSERT(result5); - DQN_ASSERT(stack.block != blockToReturnTo); - DQN_ASSERT(stack.tmp_region_count == 1); - memGuard1.region.keep_head_changes = true; + DQN_ASSERT(stack.block != block_to_return_to); + DQN_ASSERT(stack.mem_region_count == 1); + stack.MemRegionSave(&mem_guard1); } - DQN_ASSERT(stack.block != blockToReturnTo); - DQN_ASSERT(stack.block->prev_block == blockToReturnTo); - DQN_ASSERT(stack.tmp_region_count == 0); + DQN_ASSERT(stack.block != block_to_return_to); + DQN_ASSERT(stack.block->prev_block == block_to_return_to); + DQN_ASSERT(stack.mem_region_count == 0); stack.Free(); } @@ -148,17 +148,17 @@ FILE_SCOPE void DqnMemStack_Test() // Check temporary regions with tail and head pushes if (1) { - auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); auto *pop1 = stack.Push(222); auto *pop2 = stack.Push(333, DqnMemStack::PushType::Tail); - DqnMemStack::Block *blockToReturnTo = stack.block; - auto headBefore = blockToReturnTo->head; - auto tail_before = blockToReturnTo->tail; + DqnMemStack::Block *block_to_return_to = stack.block; + auto head_before = block_to_return_to->head; + auto tail_before = block_to_return_to->tail; if (1) { - auto memGuard1 = stack.TempRegionGuard(); + auto mem_guard1 = stack.MemRegionScope(); auto *result2 = stack.Push(100); auto *result3 = stack.Push(100, DqnMemStack::PushType::Tail); auto *result4 = stack.Push(100); @@ -166,19 +166,19 @@ FILE_SCOPE void DqnMemStack_Test() DQN_ASSERT(result2 && result3 && result4 && result5); DQN_ASSERT(result3 > result5); DQN_ASSERT(result2 < result4); - DQN_ASSERT(stack.block->head > headBefore && stack.block->head < stack.block->tail); + DQN_ASSERT(stack.block->head > head_before && stack.block->head < stack.block->tail); DQN_ASSERT(stack.block->tail >= stack.block->head && stack.block->tail < (stack.block->memory + stack.block->size)); - DQN_ASSERT(stack.block->memory == blockToReturnTo->memory); + DQN_ASSERT(stack.block->memory == block_to_return_to->memory); // Force allocation of new block auto *result6 = stack.Push(DQN_MEGABYTE(5)); DQN_ASSERT(result6); - DQN_ASSERT(stack.block != blockToReturnTo); - DQN_ASSERT(stack.tmp_region_count == 1); + DQN_ASSERT(stack.block != block_to_return_to); + DQN_ASSERT(stack.mem_region_count == 1); } - DQN_ASSERT(stack.block == blockToReturnTo); - DQN_ASSERT(stack.block->head == headBefore); + DQN_ASSERT(stack.block == block_to_return_to); + DQN_ASSERT(stack.block->head == head_before); DQN_ASSERT(stack.block->tail == tail_before); stack.Pop(pop1); @@ -188,7 +188,7 @@ FILE_SCOPE void DqnMemStack_Test() stack.Free(); } - Log(Status::Ok, "Temporary regions return state and/or keep changes if requested."); + Log(Status::Ok, "Temporary regions revert state and save state"); } // Check Fixed Mem Init @@ -199,11 +199,11 @@ FILE_SCOPE void DqnMemStack_Test() { isize const buf_size = sizeof(DqnMemStack::Block) * 5; char buf[buf_size] = {}; - auto stack = DqnMemStack(&buf, buf_size, Dqn::ZeroClear::No); + auto stack = DqnMemStack(&buf, buf_size, Dqn::ZeroMem::No); DQN_ASSERT(stack.block); DQN_ASSERT(stack.block->prev_block == false); - DQN_ASSERT(stack.tmp_region_count == 0); + DQN_ASSERT(stack.mem_region_count == 0); DQN_ASSERT(stack.flags == DqnMemStack::Flag::NonExpandable); auto *result1 = stack.Push(32); @@ -214,7 +214,7 @@ FILE_SCOPE void DqnMemStack_Test() DQN_ASSERT(result2 == nullptr); DQN_ASSERT(stack.block); DQN_ASSERT(stack.block->prev_block == false); - DQN_ASSERT(stack.tmp_region_count == 0); + DQN_ASSERT(stack.mem_region_count == 0); DQN_ASSERT(stack.flags == DqnMemStack::Flag::NonExpandable); stack.Free(); @@ -229,7 +229,7 @@ FILE_SCOPE void DqnMemStack_Test() usize size = 32; usize additional_size = DqnMemStack::MINIMUM_BLOCK_SIZE; - auto stack = DqnMemStack(size, Dqn::ZeroClear::Yes, 0); + auto stack = DqnMemStack(size, Dqn::ZeroMem::Yes, 0); auto *block1 = stack.block; size += additional_size; @@ -256,14 +256,14 @@ FILE_SCOPE void DqnMemStack_Test() DQN_ASSERT(block2->prev_block == block1); DQN_ASSERT(block1->prev_block == nullptr); - DQN_ASSERT(stack.FreeMemBlock(block4)); + DQN_ASSERT(stack.FreeBlock(block4)); DQN_ASSERT(stack.block == block5); DQN_ASSERT(block5->prev_block == block3); DQN_ASSERT(block3->prev_block == block2); DQN_ASSERT(block2->prev_block == block1); DQN_ASSERT(block1->prev_block == nullptr); - DQN_ASSERT(stack.FreeMemBlock(block5)); + DQN_ASSERT(stack.FreeBlock(block5)); DQN_ASSERT(stack.block == block3); DQN_ASSERT(block3->prev_block == block2); DQN_ASSERT(block2->prev_block == block1); @@ -277,7 +277,7 @@ FILE_SCOPE void DqnMemStack_Test() // Check bounds guard places magic values if (1) { - auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); char *result = static_cast(stack.Push(64)); // TODO(doyle): check head and tail are adjacent to the bounds of the allocation @@ -295,17 +295,17 @@ FILE_SCOPE void DqnMemStack_Test() // Push to tail and head if (1) { - DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); auto *result1 = stack.Push(100); auto *result2 = stack.Push(100, DqnMemStack::PushType::Tail); - auto *headBefore = stack.block->head; + auto *head_before = stack.block->head; auto *tail_before = stack.block->tail; DQN_ASSERT(result2 && result1); DQN_ASSERT(result2 != result1 && result1 < result2); stack.Pop(result2); - DQN_ASSERT(headBefore == stack.block->head) + DQN_ASSERT(head_before == stack.block->head) DQN_ASSERT(tail_before != stack.block->tail) stack.Pop(result1); @@ -322,7 +322,7 @@ FILE_SCOPE void DqnMemStack_Test() // Push too much to tail causes expansion if (1) { - DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); auto *result1 = stack.Push(100); DQN_ASSERT(stack.block->prev_block == nullptr); @@ -352,7 +352,7 @@ FILE_SCOPE void DqnMemStack_Test() // Push too much to tail fails to expand when non expandable if (1) { - DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::NonExpandable); + DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::NonExpandable); auto *result1 = stack.Push(100); DQN_ASSERT(stack.block->prev_block == nullptr); @@ -390,11 +390,11 @@ FILE_SCOPE void DqnMemStack_Test() // Using push on head if (1) { - DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); auto *api = &stack.myHeadAPI; auto *block_before = stack.block; - auto *headBefore = stack.block->head; + auto *head_before = stack.block->head; isize buf_size = 16; char *buf = (char *)stack.Push(buf_size); @@ -408,19 +408,19 @@ FILE_SCOPE void DqnMemStack_Test() DqnMem_Set(buf, '@', buf_size); DQN_ASSERT(block_before == stack.block); - DQN_ASSERT(headBefore < stack.block->head); + DQN_ASSERT(head_before < stack.block->head); stack.Pop(buf); DQN_ASSERT(block_before == stack.block); - DQN_ASSERT(headBefore == stack.block->head); - DQN_ASSERT(headBefore == stack.block->memory); + DQN_ASSERT(head_before == stack.block->head); + DQN_ASSERT(head_before == stack.block->memory); stack.Free(); } // Using push on tail if (1) { - DqnMemStack stack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + DqnMemStack stack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); auto *api = &stack.myHeadAPI; auto *block_before = stack.block; @@ -455,11 +455,11 @@ FILE_SCOPE void DqnMemStack_Test() // Using push on head if (1) { - auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); auto *api = &stack.myHeadAPI; auto *block_before = stack.block; - auto *headBefore = stack.block->head; + auto *head_before = stack.block->head; isize buf_size = 16; char *buf = (char *)stack.Push(buf_size); @@ -476,15 +476,15 @@ FILE_SCOPE void DqnMemStack_Test() stack.Pop(buf); DQN_ASSERT(block_before == stack.block); - DQN_ASSERT(headBefore == stack.block->head); - DQN_ASSERT(headBefore == stack.block->memory); + DQN_ASSERT(head_before == stack.block->head); + DQN_ASSERT(head_before == stack.block->memory); stack.Free(); } // Using push on tail if (1) { - DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); auto *api = &stack.myHeadAPI; auto *block_before = stack.block; diff --git a/DqnUnitTest.cpp b/DqnUnitTest.cpp index 82b3359..3ba3cd9 100644 --- a/DqnUnitTest.cpp +++ b/DqnUnitTest.cpp @@ -651,7 +651,7 @@ void DqnString_Test() if (1) { DqnString str = "hello world"; - DQN_DEFER(str.Free()); + DQN_DEFER { str.Free(); }; str = "hello world2"; str.Append(", hello again"); str.Append(", and hello again"); @@ -666,7 +666,7 @@ void DqnString_Test() { DqnString str = DQN_BUFFER_STR_LIT("hello world"); - DQN_DEFER(str.Free()); + DQN_DEFER { str.Free(); }; DQN_ASSERT(DqnStr_Cmp(str.str, "hello world") == 0); Log(Status::Ok, "Copy constructor DqnSlice"); @@ -680,7 +680,7 @@ void DqnString_Test() DqnBuffer helloSlice = DQN_BUFFER_STR_LIT("hello"); str = helloSlice; - DQN_DEFER(str.Free()); + DQN_DEFER { str.Free(); }; DQN_ASSERT(DqnStr_Cmp(str.str, "hello") == 0); Log(Status::Ok, "Copy constructor (DqnFixedString<>)"); @@ -688,7 +688,7 @@ void DqnString_Test() { DqnString str = DQN_BUFFER_STR_LIT("hello world"); - DQN_DEFER(str.Free()); + DQN_DEFER { str.Free(); }; DQN_ASSERT(str.Sprintf("hello %s", "sailor")); DQN_ASSERTM(DqnStr_Cmp(str.str, "hello sailor") == 0, "Result: %s", str.str); @@ -698,7 +698,7 @@ void DqnString_Test() { { DqnString str = DQN_BUFFER_STR_LIT("hello world"); - DQN_DEFER(str.Free()); + DQN_DEFER { str.Free(); }; DQN_ASSERT(str.Sprintf("hello %s", "sailor")); str += DQN_BUFFER_STR_LIT(".end"); DQN_ASSERTM(DqnStr_Cmp(str.str, "hello sailor.end") == 0, "Result: %s", str.str); @@ -706,7 +706,7 @@ void DqnString_Test() { DqnString str = DQN_BUFFER_STR_LIT("hello world"); - DQN_DEFER(str.Free()); + DQN_DEFER { str.Free(); }; DQN_ASSERT(str.Sprintf("hello %s", "sailor")); DQN_ASSERT(str.SprintfAppend(" %d, %d", 100, 200)); DQN_ASSERT(DqnStr_Cmp(str.str, "hello sailor 100, 200") == 0); @@ -728,7 +728,7 @@ void DqnString_Test() { DqnString str = DQN_BUFFER_STR_LIT("hello world"); - DQN_DEFER(str.Free()); + DQN_DEFER { str.Free(); }; DQN_ASSERT(str.Sprintf("hello %s", "sailor")); str = str + " end" + DQN_BUFFER_STR_LIT(" of"); DQN_ASSERT(DqnStr_Cmp(str.str, "hello sailor end of") == 0); @@ -738,7 +738,7 @@ void DqnString_Test() { DqnString str = "localhost"; - DQN_DEFER(str.Free()); + DQN_DEFER { str.Free(); }; str.SprintfAppend(":%d", 16832); str += "/json_rpc"; DQN_ASSERT(str.len == 24 && DqnStr_Cmp("localhost:16832/json_rpc", str.str) == 0); @@ -1299,9 +1299,8 @@ void DqnArray_Test() if (1) { - auto stack = - DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); - DQN_DEFER(stack.Free()); + auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); + DQN_DEFER { stack.Free(); }; #if 0 if (1) { @@ -1432,12 +1431,12 @@ void DqnFile_Test() size_t bytesToWrite = DqnStr_Len(writeData[i]); u8 *dataToWrite = (u8 *)(writeData[i]); - size_t bytesWritten = file->Write(dataToWrite, bytesToWrite, 0); + size_t bytesWritten = file->Write(dataToWrite, bytesToWrite); DQN_ASSERT(bytesWritten == bytesToWrite); file->Close(); } - auto memstack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + auto memstack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); // Read data back in for (u32 i = 0; i < DQN_ARRAY_COUNT(file_names); i++) { @@ -1573,7 +1572,7 @@ FILE_SCOPE void DqnJobQueue_Test() LOG_HEADER(); global_debug_counter = 0; - auto memstack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + auto memstack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); u32 num_threads, num_cores; DqnOS_GetThreadsAndCores(&num_cores, &num_threads); @@ -1617,7 +1616,7 @@ void DqnQuickSort_Test() auto state = DqnRndPCG(); if (1) { - auto stack = DqnMemStack(DQN_KILOBYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); + auto stack = DqnMemStack(DQN_KILOBYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard); // Create array of ints u32 num_ints = 1000000; diff --git a/DqnVHashTable.cpp b/DqnVHashTable.cpp index 67d2226..516a124 100644 --- a/DqnVHashTable.cpp +++ b/DqnVHashTable.cpp @@ -11,7 +11,7 @@ void DqnVHashTable_Test() Block block = {}; DqnVHashTable table = {}; - DQN_DEFER(table.Free()); + DQN_DEFER { table.Free(); }; table.Set(12, block); Block *getResult = table.Get(12); @@ -32,7 +32,7 @@ void DqnVHashTable_Test() { Block blocks[] = {{0}, {1}, {2}, {3}, {4}}; DqnVHashTable table = {}; - DQN_DEFER(table.Free()); + DQN_DEFER { table.Free(); }; table.Set(1, blocks[0]); table.Set(2, blocks[1]); diff --git a/dqn.h b/dqn.h index 2777c6b..b35c5a0 100644 --- a/dqn.h +++ b/dqn.h @@ -169,27 +169,27 @@ using f32 = float; #define DQN_SIZEOF(decl) (isize)sizeof(decl) template -struct DqnDefer__ +struct DqnDefer_ { - DqnDefer__(Proc p) : proc(p) { } - ~DqnDefer__() { proc(); } + DqnDefer_(Proc p) : proc(p) { } + ~DqnDefer_() { proc(); } Proc proc; }; -template -DqnDefer__ DqnDeferFunc__(Proc p) +struct DqnDeferHelper_ { - return DqnDefer__(p); -} + template + DqnDefer_ operator+(Proc proc) { return DqnDefer_(proc); }; +}; -#define DQN_DEFER(code) auto DQN_UNIQUE_NAME(dqnDeferLambda__) = DqnDeferFunc__([&]()->void {code;}) +#define DQN_DEFER const auto DQN_UNIQUE_NAME(dqn_defer_lambda_) = DqnDeferHelper_() + [&]() // #Dqn Namespace namespace Dqn { -enum struct ZeroClear { No = 0, Yes = 1}; -enum struct IgnoreCase { No = 0, Yes = 1}; -FILE_SCOPE const bool IS_DEBUG = true; +enum struct ZeroMem { No = 0, Yes = 1}; +enum struct IgnoreCase { No = 0, Yes = 1}; +FILE_SCOPE const bool IsDebug = true; }; // namespace Dqn // #External Code @@ -1276,17 +1276,16 @@ struct DqnArray isize max; T *data; - DqnArray () = default; - DqnArray (DqnAllocator *allocator) { *this = {}; this->allocator = allocator; } - // ~DqnArray () { if (this->data && this->mem_api) this->mem_api->Free(data); } + DqnArray () = default; + DqnArray (DqnAllocator *allocator) { *this = {}; this->allocator = allocator; } + DqnArray (T *data_, isize max_, isize len_ = 0) { *this = {}; this->allocator = nullptr; this->data = data_; this->max = max_; this->len = len_; } - void UseMemory (T *data_, isize max_, isize len_ = 0) { this->mem_api = nullptr; this->data = data_; this->max = max_; this->len = len_; } - void Clear (Dqn::ZeroClear clear = Dqn::ZeroClear::No) { if (!data) return; len = 0; if (clear == Dqn::ZeroClear::Yes) DqnMem_Clear(data, 0, sizeof(T) * max); } - void Free () { if (data) { allocator->Free(data); } *this = {}; } - T *Front () { DQN_ASSERT(len > 0); return data + 0; } - T *Back () { DQN_ASSERT(len > 0); return data + (len - 1); } - void Resize (isize new_len) { if (new_len > max) Reserve(GrowCapacity_(new_len)); len = new_len; } - void Resize (isize new_len, T const *v) { if (new_len > max) Reserve(GrowCapacity_(new_len)); if (new_len > len) for (isize n = len; n < new_len; n++) data[n] = *v; len = new_len; } + void Clear (Dqn::ZeroMem clear = Dqn::ZeroMem::No) { if (!data) return; len = 0; if (clear == Dqn::ZeroMem::Yes) DqnMem_Clear(data, 0, sizeof(T) * max); } + void Free () { if (data) { allocator->Free(data); } *this = {}; } + T *Front () { DQN_ASSERT(len > 0); return data + 0; } + T *Back () { DQN_ASSERT(len > 0); return data + (len - 1); } + void Resize (isize new_len) { if (new_len > max) Reserve(GrowCapacity_(new_len)); len = new_len; } + void Resize (isize new_len, T const *v) { if (new_len > max) Reserve(GrowCapacity_(new_len)); if (new_len > len) for (isize n = len; n < new_len; n++) data[n] = *v; len = new_len; } void Reserve (isize new_max); T *Make (isize len = 1) { len += len; if (len > max) Reserve(GrowCapacity_(len)); return &data[len - len]; } T *Push (T const &v) { if (len + 1 > max) Reserve(GrowCapacity_(len + 1)); data[len++] = v; return data + (len-1); } @@ -1459,16 +1458,16 @@ struct DqnMemStack DqnAllocator *block_allocator; // Read: Allocator used to allocator blocks for this memory stack Block *block; // Read: Memory block allocated for the stack u32 flags; // Read - i32 tmp_region_count;// Read: The number of temp memory regions in use + i32 mem_region_count;// Read: The number of temp memory regions in use DqnMemStack() = default; // Uses fixed memory, will be sourced from the buffer and assert after buffer is full. - DqnMemStack(void *mem, isize size, Dqn::ZeroClear clear, u32 flags_ = 0); + DqnMemStack(void *mem, isize size, Dqn::ZeroMem clear, u32 flags_ = 0); // Memory Stack capable of expanding when full, but only if NonExpandable flag is not set. - DqnMemStack (isize size, Dqn::ZeroClear clear, u32 flags_ = 0, DqnAllocator *block_allocator_ = DQN_DEFAULT_ALLOCATOR) { LazyInit(size, clear, flags_, block_allocator_); } - void LazyInit(isize size, Dqn::ZeroClear clear, u32 flags_ = 0, DqnAllocator *block_allocator_ = DQN_DEFAULT_ALLOCATOR); + DqnMemStack (isize size, Dqn::ZeroMem clear, u32 flags_ = 0, DqnAllocator *block_allocator_ = DQN_DEFAULT_ALLOCATOR) { LazyInit(size, clear, flags_, block_allocator_); } + void LazyInit(isize size, Dqn::ZeroMem clear, u32 flags_ = 0, DqnAllocator *block_allocator_ = DQN_DEFAULT_ALLOCATOR); // Allocation API // ============================================================================================= @@ -1476,69 +1475,45 @@ struct DqnMemStack // Allocate memory from the MemStack. // alignment: Ptr returned from allocator is aligned to this value and MUST be power of 2. - // return: nullptr if out of space OR stack is using fixed memory/size OR stack full and platform malloc fails. + // return: nullptr if out of space OR stack is using fixed memory/size and out of memory OR stack full and malloc fails (or flags prevent expansion). void *Push (isize size, PushType push_type = PushType::Default, u8 alignment = 4); - void SetDefaultAllocate(PushType type) { if (type == PushType::Default) return; if (type == PushType::Head) flags |= Flag::DefaultAllocateTail; else flags &= ~Flag::DefaultAllocateTail; } - // Frees the given ptr. It MUST be the last allocated item in the stack, asserts otherwise. - void Pop (void *ptr, Dqn::ZeroClear clear = Dqn::ZeroClear::No); - - // Frees all blocks belonging to this stack. - void Free (); - - // Frees the specified block belonging to the stack. - // return: FALSE if block doesn't belong this into calls DqnMem_Free() or invalid args. - bool FreeMemBlock (Block *mem_block); - - // Frees the last-most memory block. If last block, free that block making the MemStack blockless. - // Next allocate will attach a block. - bool FreeLastBlock (); - - // Reverts the stack and its usage back to the first block - void Reset (); - void ResetTail (); - - // Reset the current memory block usage to 0. - void ClearCurrBlock(Dqn::ZeroClear clear = Dqn::ZeroClear::No); - Info GetInfo () const; + void SetDefaultAllocate(PushType type) { if (type == PushType::Default) return; if (type == PushType::Head) flags &= ~Flag::DefaultAllocateTail; else flags |= Flag::DefaultAllocateTail; } + void Pop (void *ptr, Dqn::ZeroMem zero = Dqn::ZeroMem::No); // Free the ptr. MUST be the last allocated ptr on the block head or tail, assert otherwise. + void PopBlock () { FreeBlock(block); } + void Free () { if (flags & Flag::BoundsGuard) tracker.allocations.Free(); while (block_allocator && block) PopBlock(); } + bool FreeBlock (DqnMemStack::Block *mem_block); + void Reset (Dqn::ZeroMem zero) { while(block && block->prev_block) PopBlock(); ClearCurrBlock(zero); } + void ResetTail (); // Reset just the tail + void ClearCurrBlock (Dqn::ZeroMem zero = Dqn::ZeroMem::No); // Reset the current memory block usage to 0. + Info GetInfo () const; // Temporary Memory Regions API // ============================================================================================= - // TODO(doyle): Look into a way of "preventing/guarding" against anual calls to free/clear in temp regions - struct TempRegion + // Revert all allocations between the Begin() and End() regions. Guard version is RAII'ed. + enum struct RegionIsScoped { Yes, No }; + struct MemRegion { - DqnMemStack *stack; // Stack associated with this TempRegion - Block *starting_block; // Remember the block to revert to and its memory usage. + DqnMemStack *stack; // Stack associated with this MemRegion + Block *starting_block; // The block to revert back to char *starting_block_head; char *starting_block_tail; - bool keep_head_changes = false; - bool keep_tail_changes = false; }; - struct TempRegionGuard_ + struct MemRegionScoped { - TempRegionGuard_(DqnMemStack *stack); - ~TempRegionGuard_(); - TempRegion region; + MemRegionScoped(DqnMemStack *stack) { region = stack->MemRegionBegin(); } + ~MemRegionScoped() { if (region.stack) region.stack->MemRegionEnd(region); } + MemRegion region; }; - // Revert all allocations between the Begin() and End() regions. Guard version is RAII'ed. - TempRegion TempRegionBegin (); - void TempRegionEnd (TempRegion region); - TempRegionGuard_ TempRegionGuard (); + MemRegion MemRegionBegin (); + void MemRegionEnd (MemRegion region); + MemRegionScoped MemRegionScope () { return MemRegionScoped(this); }; // Keep allocations that have occurred since Begin(). End() does not need to be called anymore. - void TempRegionKeepChanges(TempRegion region); - - void *MallocHead (size_t size) { return Push(size); } - void *CallocHead (size_t size) { void *result = Push(size); DqnMem_Clear(result, 0, size); } - void FreeHead (void *ptr) { (void)ptr; return; } - void *ReallocHead(void *ptr, size_t size) { DqnPtrHeader *header = tracker.PtrToHeader((char *)ptr); void *result = Push(size); DqnMem_Copy(result, ptr, header->alloc_amount); return result; } - - void *MallocTail (size_t size) { return Push(size, PushType::Tail); } - void *CallocTail (size_t size) { void *result = Push(size, PushType::Tail); DqnMem_Clear(result, 0, size); } - void FreeTail (void *ptr) { (void)ptr; return; } - void *ReallocTail(void *ptr, size_t size) { DqnPtrHeader *header = tracker.PtrToHeader((char *)ptr); void *result = Push(size, PushType::Tail); DqnMem_Copy(result, ptr, header->alloc_amount); return result; } + void MemRegionSave (MemRegion *region) { DQN_ASSERT(region->stack == this); region->stack = nullptr; mem_region_count--; DQN_ASSERT(mem_region_count >= 0); } + void MemRegionSave (MemRegionScoped *scope) { MemRegionSave(&scope->region); } }; // #DqnHash API @@ -1830,7 +1805,7 @@ struct DqnString int VSprintfAppend (char const *fmt, va_list va) { return VSprintfAtOffset(fmt, va, len/*offset*/); } void NullTerminate () { str[len] = 0; } // NOTE: If you modify the storage directly, this can be handy. - void Clear (Dqn::ZeroClear clear = Dqn::ZeroClear::No) { if (clear == Dqn::ZeroClear::Yes) DqnMem_Set(str, 0, max); len = max = 0; NullTerminate(); } + void Clear (Dqn::ZeroMem clear = Dqn::ZeroMem::No) { if (clear == Dqn::ZeroMem::Yes) DqnMem_Set(str, 0, max); len = max = 0; NullTerminate(); } void Free () { if (str) allocator->Free(str); str = nullptr; } void Resize (int new_max) { if (new_max > max) Reserve(new_max); len = DQN_MIN(new_max, len); NullTerminate(); } void Reserve (int new_max); @@ -1886,15 +1861,14 @@ struct DqnFixedString int VSprintfAppend (char const *fmt, va_list va) { return VSprintfAtOffset(fmt, va, len/*offset*/); } void NullTerminate () { str[len] = 0; } // NOTE: If you modify the storage directly, this can be handy. - void Clear (Dqn::ZeroClear clear = Dqn::ZeroClear::No) { if (clear == Dqn::ZeroClear::Yes) DqnMem_Set(str, 0, MAX); *this = {}; } + void Clear (Dqn::ZeroMem clear = Dqn::ZeroMem::No) { if (clear == Dqn::ZeroMem::Yes) DqnMem_Set(str, 0, MAX); *this = {}; } int VSprintfAtOffset(char const *fmt, va_list va, int offset) { + if (Dqn::IsDebug) DQN_ASSERT(Dqn_vsnprintf(nullptr, 0, fmt, va) < MAX); char *start = str + offset; int result = Dqn_vsnprintf(start, static_cast((str + MAX) - start), fmt, va); len = (offset + result); - if (Dqn::IS_DEBUG) DQN_ASSERT(Dqn_vsnprintf(nullptr, 0, fmt, va) < MAX); - return result; } }; @@ -2034,7 +2008,7 @@ struct DqnVArray void LazyInit (isize size) { *this = {}; if (data) return; len = 0; max = size; data = (T *)DqnOS_VAlloc(max * sizeof(T)); DQN_ALWAYS_ASSERT(data); } // ~DqnVArray () { if (data) DqnOS_VFree(data, sizeof(T) * max); } - void Clear (Dqn::ZeroClear clear = Dqn::ZeroClear::No) { if (data) { len = 0; if (clear == Dqn::ZeroClear::Yes) DqnMem_Clear(data, 0, sizeof(T) * max); } } + void Clear (Dqn::ZeroMem clear = Dqn::ZeroMem::No) { if (data) { len = 0; if (clear == Dqn::ZeroMem::Yes) DqnMem_Clear(data, 0, sizeof(T) * max); } } void Free () { if (data) { DqnOS_VFree(data, sizeof(T) * max); } *this = {}; } T *Front () { return (len > 0) ? (data + 0) : nullptr; } T *Back () { return (len > 0) ? (data + (len - 1)) : nullptr; } @@ -2183,8 +2157,8 @@ struct DqnVHashTable Entry &operator* () const { return *GetCurrEntry(); } Iterator &operator++(); Iterator &operator--() { if (--index_in_bucket < 0) { index_in_bucket = 0; num_used_buckets = DQN_MAX(--num_used_buckets, 0); } entry = GetCurrEntry(); return *this; } - Iterator operator++(int) { Iterator result = *this; ++(*this); return result; } - Iterator operator--(int) { Iterator result = *this; --(*this); return result; } + Iterator operator++(int) { Iterator result = *this; ++(*this); return result; } // postfix + Iterator operator--(int) { Iterator result = *this; --(*this); return result; } // postfix Iterator operator+ (int offset) const { Iterator result = *this; DQN_FOR_EACH(i, DQN_ABS(offset)) { (offset > 0) ? ++result : --result; } return result; } // TODO(doyle): Improve Iterator operator- (int offset) const { Iterator result = *this; DQN_FOR_EACH(i, DQN_ABS(offset)) { (offset > 0) ? --result : ++result; } return result; } // TODO(doyle): Improve @@ -2194,10 +2168,8 @@ struct DqnVHashTable isize index_in_bucket; }; - Iterator Begin() { return begin(); } - Iterator End() { return end(); } - Iterator begin() { return Iterator(this); } - Iterator end() { return Iterator(this, num_buckets, DQN_ARRAY_COUNT(this->buckets[0].entries)); } + Iterator begin() { return Iterator(this); } + Iterator end() { return Iterator(this, num_buckets, DQN_ARRAY_COUNT(this->buckets[0].entries)); } }; DQN_VHASH_TABLE_TEMPLATE DQN_VHASH_TABLE_DECL::Iterator::Iterator(DqnVHashTable *table_, @@ -2368,6 +2340,7 @@ struct DqnFile u32 flags; void *handle; usize size; + int curr_write_offset; // API // ============================================================================================== @@ -2379,9 +2352,9 @@ struct DqnFile bool Open(char const *path, u32 const flags_, Action const action); bool Open(wchar_t const *path, u32 const flags_, Action const action); - // fileOffset: The byte offset to starting writing from. + // file_offset: The byte offset to starting writing from. // return: The number of bytes written. 0 if invalid args or it failed to write. - usize Write(u8 const *buf, usize const num_bytes_to_write, usize const fileOffset); + usize Write(u8 const *buf, usize const num_bytes_to_write); // IMPORTANT: You may want to allocate size+1 for null-terminating the file contents when reading into a buffer. // return: The number of bytes read. 0 if invalid args or it failed to read. @@ -2551,7 +2524,7 @@ DQN_CATALOG_TEMPLATE T *DQN_CATALOG_DECL::GetIfUpdated(DqnCatalogPath const &fil DQN_CATALOG_TEMPLATE bool DQN_CATALOG_DECL::PollAssets() { bool result = false; - for (auto it = this->asset_table.Begin(); it != this->asset_table.End(); ++it) + for (auto it = this->asset_table.begin(); it != this->asset_table.end(); ++it) { DqnCatalogPath const *file = &it.entry->key; Entry *entry = &it.entry->item; @@ -2731,7 +2704,7 @@ DQN_FILE_SCOPE void DqnWin32_OutputDebugString(const char *const fmt_str, ...); // buf: Filled with the path to the executable file. // return: The offset to the last backslash. -1 if buf_len was not large enough or buf is null. (i.e. // buf + offsetToLastSlash + 1, gives C:/Path/) -DQN_FILE_SCOPE i32 DqnWin32_GetEXEDirectory(char *const buf, const u32 buf_len); +DQN_FILE_SCOPE i32 DqnWin32_GetExeDirectory(wchar_t *const buf, const u32 buf_len); #endif // DQN_IS_WIN32 #endif // DQN_PLATFORM_H #endif // DQN_PLATFORM_HEADER @@ -2948,9 +2921,9 @@ void DqnMemTracker::CheckAllocations() const // #DqnMemStack // ================================================================================================= DQN_FILE_SCOPE DqnMemStack::Block * -DqnMemStack__AllocateBlock(isize size, Dqn::ZeroClear clear, DqnAllocator *allocator) +DqnMemStack__AllocateBlock(isize size, Dqn::ZeroMem clear, DqnAllocator *allocator) { - bool zero = clear == Dqn::ZeroClear::Yes; + bool zero = clear == Dqn::ZeroMem::Yes; isize total_size = sizeof(DqnMemStack::Block) + size; auto *result = zero ? static_cast(allocator->Calloc(1, total_size)) : static_cast(allocator->Malloc(total_size)); @@ -2961,13 +2934,13 @@ DqnMemStack__AllocateBlock(isize size, Dqn::ZeroClear clear, DqnAllocator *alloc return result; } -DqnMemStack::DqnMemStack(void *mem, isize size, Dqn::ZeroClear clear, u32 flags_) +DqnMemStack::DqnMemStack(void *mem, isize size, Dqn::ZeroMem clear, u32 flags_) { DQN_ALWAYS_ASSERTM(mem, "Supplied fixed memory buffer is nullptr, initialise with fixed memory failed"); DQN_ALWAYS_ASSERTM(size > DQN_SIZEOF(DqnMemStack::Block), "(%zu < %zu) Buffer too small for block metadata", size, DQN_SIZEOF(DqnMemStack::Block)); *this = {}; - if (clear == Dqn::ZeroClear::Yes) + if (clear == Dqn::ZeroMem::Yes) DqnMem_Set(mem, 0, size); char *block_offset = static_cast(mem) + sizeof(*this->block); @@ -2981,7 +2954,7 @@ DqnMemStack::DqnMemStack(void *mem, isize size, Dqn::ZeroClear clear, u32 flags_ this->tracker.Init(bounds_guard); } -void DqnMemStack::LazyInit(isize size, Dqn::ZeroClear clear, u32 flags_, DqnAllocator *block_allocator_) +void DqnMemStack::LazyInit(isize size, Dqn::ZeroMem clear, u32 flags_, DqnAllocator *block_allocator_) { DQN_ALWAYS_ASSERTM(size > 0, "%zu <= 0", size); *this = {}; @@ -3001,7 +2974,7 @@ void *DqnMemStack::Push(isize size, PushType push_type, u8 alignment) return nullptr; if (!this->block) - LazyInit(MINIMUM_BLOCK_SIZE, Dqn::ZeroClear::Yes, Flag::DefaultFlags, DQN_DEFAULT_ALLOCATOR); + LazyInit(MINIMUM_BLOCK_SIZE, Dqn::ZeroMem::Yes, Flag::DefaultFlags, DQN_DEFAULT_ALLOCATOR); isize size_to_alloc = this->tracker.GetAllocationSize(size, alignment); bool push_to_head = true; @@ -3033,7 +3006,7 @@ void *DqnMemStack::Push(isize size, PushType push_type, u8 alignment) } isize new_block_size = DQN_MAX(size_to_alloc, MINIMUM_BLOCK_SIZE); - Block *new_block = DqnMemStack__AllocateBlock(new_block_size, Dqn::ZeroClear::No, this->block_allocator); + Block *new_block = DqnMemStack__AllocateBlock(new_block_size, Dqn::ZeroMem::No, this->block_allocator); new_block->prev_block = this->block; this->block = new_block; } @@ -3114,7 +3087,7 @@ FILE_SCOPE void DqnMemStack__KillTrackedPtrsInBlock(DqnMemTracker *tracker, DqnM DqnMemStack__KillTrackedPtrsInRange(tracker, block_start, block_end); } -void DqnMemStack::Pop(void *ptr, Dqn::ZeroClear clear) +void DqnMemStack::Pop(void *ptr, Dqn::ZeroMem clear) { if (!ptr) return; @@ -3147,28 +3120,17 @@ void DqnMemStack::Pop(void *ptr, Dqn::ZeroClear clear) DQN_ASSERT(this->block->tail <= block_end); } - if (clear == Dqn::ZeroClear::Yes) + if (clear == Dqn::ZeroMem::Yes) DqnMem_Set(start, 0, end - start); if (this->block->tail == block_end && this->block->head == this->block->memory) { if (this->block->prev_block) - { - this->FreeLastBlock(); - } + this->PopBlock(); } } -void DqnMemStack::Free() -{ - if (Dqn_BitIsSet(this->flags, Flag::BoundsGuard)) - this->tracker.allocations.Free(); - - while (this->block_allocator && this->block) - this->FreeLastBlock(); -} - -bool DqnMemStack::FreeMemBlock(DqnMemStack::Block *mem_block) +bool DqnMemStack::FreeBlock(DqnMemStack::Block *mem_block) { if (!mem_block || !this->block) return false; @@ -3193,7 +3155,7 @@ bool DqnMemStack::FreeMemBlock(DqnMemStack::Block *mem_block) this->block_allocator->Free(block_to_free); // No more blocks, then last block has been freed - if (!this->block) DQN_ASSERT(this->tmp_region_count == 0); + if (!this->block) DQN_ASSERT(this->mem_region_count == 0); return true; } @@ -3212,38 +3174,19 @@ void DqnMemStack::ResetTail() this->block->tail = end; } -void DqnMemStack::Reset() -{ - while(this->block && this->block->prev_block) - { - this->FreeLastBlock(); - } - this->ClearCurrBlock(Dqn::ZeroClear::No); -} - - -bool DqnMemStack::FreeLastBlock() -{ - bool result = this->FreeMemBlock(this->block); - return result; -} - -void DqnMemStack::ClearCurrBlock(Dqn::ZeroClear clear) +void DqnMemStack::ClearCurrBlock(Dqn::ZeroMem zero) { if (this->block) { if (Dqn_BitIsSet(this->flags, Flag::BoundsGuard)) - { DqnMemStack__KillTrackedPtrsInBlock(&this->tracker, this->block); - } this->block->head = this->block->memory; this->block->tail = this->block->memory + this->block->size; - if (clear == Dqn::ZeroClear::Yes) + if (zero == Dqn::ZeroMem::Yes) { DqnMem_Clear(this->block->memory, 0, this->block->size); } - } } @@ -3270,118 +3213,45 @@ DqnMemStack::Info DqnMemStack::GetInfo() const return result; } -DqnMemStack::TempRegion DqnMemStack::TempRegionBegin() +DqnMemStack::MemRegion DqnMemStack::MemRegionBegin() { - TempRegion result = {}; - result.stack = this; - result.starting_block = this->block; - result.starting_block_head = (this->block) ? this->block->head : nullptr; - result.starting_block_tail = (this->block) ? this->block->tail : nullptr; + MemRegion result = {}; + result.stack = this; + if (this->block) + { + result.starting_block = this->block; + result.starting_block_head = this->block->head; + result.starting_block_tail = this->block->tail; + } - this->tmp_region_count++; + this->mem_region_count++; return result; } -void DqnMemStack::TempRegionEnd(TempRegion region) +void DqnMemStack::MemRegionEnd(MemRegion region) { DQN_ASSERT(region.stack == this); - this->tmp_region_count--; - DQN_ASSERT(this->tmp_region_count >= 0); + this->mem_region_count--; + DQN_ASSERT(this->mem_region_count >= 0); - if (region.keep_head_changes && region.keep_tail_changes) - { - return; - } + while (this->block != region.starting_block) + this->PopBlock(); - // Free blocks until you find the first block with changes in the head or tail, this is the - // block we want to start preserving allocation data for keepHead/TailChanges. - if (region.keep_head_changes) + if (this->block) { - while (this->block && this->block->head == this->block->memory) - this->FreeLastBlock(); - } - else if (region.keep_tail_changes) - { - while (this->block && this->block->tail == (this->block->memory + this->block->size)) - this->FreeLastBlock(); - } - else - { - while (this->block != region.starting_block) - this->FreeLastBlock(); - } + this->block->head = region.starting_block_head; + this->block->tail = region.starting_block_tail; - for (Block *block_ = this->block; block_; block_ = block_->prev_block) - { - if (block_ == region.starting_block) + if (this->flags & DqnMemStack::Flag::BoundsGuard) { - if (region.keep_head_changes) - { - block_->tail = region.starting_block_tail; - } - else if (region.keep_tail_changes) - { - block_->head = region.starting_block_head; - } - else - { - block_->head = region.starting_block_head; - block_->tail = region.starting_block_tail; - } - - if (Dqn_BitIsSet(this->flags, DqnMemStack::Flag::BoundsGuard)) - { - char *block_start = this->block->head; - char *block_end = this->block->tail; - DqnMemStack__KillTrackedPtrsInRange(&this->tracker, block_start, block_end); - } - break; - } - else - { - if (region.keep_head_changes || region.keep_tail_changes) - { - char *block_start = nullptr; - char *block_end = nullptr; - if (region.keep_head_changes) - { - block_start = block_->tail; - block_end = block_->memory + block_->size; - block_->tail = block_end; - } - else - { - block_start = block_->memory; - block_end = block_->memory + block_->size; - block_->head = block_start; - } - - if (Dqn_BitIsSet(this->flags, DqnMemStack::Flag::BoundsGuard)) - { - DqnMemStack__KillTrackedPtrsInRange(&this->tracker, block_start, block_end); - } - } + char *block_start = this->block->head; + char *block_end = this->block->tail; + DqnMemStack__KillTrackedPtrsInRange(&this->tracker, block_start, block_end); } } } -DqnMemStack::TempRegionGuard_ DqnMemStack::TempRegionGuard() -{ - return TempRegionGuard_(this); -} - -DqnMemStack::TempRegionGuard_::TempRegionGuard_(DqnMemStack *stack) -{ - this->region = stack->TempRegionBegin(); -} - -DqnMemStack::TempRegionGuard_::~TempRegionGuard_() -{ - DqnMemStack *const stack = this->region.stack; - stack->TempRegionEnd(this->region); -} - // #DqnHash // ================================================================================================= // Taken from GingerBill single file library @ github.com/gingerbill/gb @@ -5332,7 +5202,7 @@ char const *DqnLogger::Log(Type type, Context const log_context, char const *fmt { va_list va; va_start(va, fmt); - DQN_DEFER(va_end(va)); + DQN_DEFER { va_end(va); }; LOCAL_PERSIST DqnFixedString2048 fmt_msg; fmt_msg.Clear(); @@ -7413,7 +7283,7 @@ DQN_FILE__LIST_DIR(DqnFile__PlatformListDir) return nullptr; } - DQN_DEFER(FindClose(find_handle)); + DQN_DEFER { FindClose(find_handle); }; bool stay_in_loop = true; while (stay_in_loop) { @@ -7453,7 +7323,7 @@ DQN_FILE__LIST_DIR(DqnFile__PlatformListDir) return nullptr; } - DQN_DEFER(FindClose(find_handle)); + DQN_DEFER { FindClose(find_handle); }; char **list = (char **)allocator->Calloc(1, sizeof(*list) * (curr_num_files)); if (!list) @@ -7506,7 +7376,7 @@ FILE_SCOPE bool DqnFile__UnixGetFileSize(char const *path, usize *size) // But there can also be zero-byte files, we can't be sure. So manual check by counting bytes if (size && FILE *file = fopen(path, "rb")) { - DQN_DEFER(fclose(file)); + DQN_DEFER { fclose(file); }; while (fgetc(file) != EOF) { (*size)++; @@ -7586,7 +7456,7 @@ DQN_FILE__LIST_DIR(DqnFile__PlatformListDir) { DIR *const dir_handle = opendir(dir); if (!dir_handle) return nullptr; - DQN_DEFER(closedir(dir_handle)); + DQN_DEFER { closedir(dir_handle); }; struct dirent *dir_file = readdir(dir_handle); while (dir_file) @@ -7606,7 +7476,7 @@ DQN_FILE__LIST_DIR(DqnFile__PlatformListDir) { DIR *const dir_handle = opendir(dir); if (!dir_handle) return nullptr; - DQN_DEFER(closedir(dir_handle)); + DQN_DEFER { closedir(dir_handle); }; char **list = (char **)allocator->Calloc(1, sizeof(*list) * curr_num_files); if (!list) @@ -7670,13 +7540,14 @@ bool DqnFile::Open(wchar_t const *path, u32 flags_, Action action) #endif } -usize DqnFile::Write(u8 const *buf, usize num_bytes_to_write, usize fileOffset) +usize DqnFile::Write(u8 const *buf, usize num_bytes_to_write) { // TODO(doyle): Implement when it's needed - DQN_ASSERTM(fileOffset == 0, "File writing into offset is not implemented."); + usize file_offset = 0; usize num_bytes_written = 0; #if defined(DQN_IS_WIN32) + DQN_ALWAYS_ASSERTM(file_offset == 0, "File writing into offset is not implemented."); DWORD bytes_to_write = (DWORD)num_bytes_to_write; DWORD bytes_written; BOOL result = WriteFile(this->handle, (void *)buf, bytes_to_write, &bytes_written, nullptr); @@ -7692,7 +7563,6 @@ usize DqnFile::Write(u8 const *buf, usize num_bytes_to_write, usize fileOffset) const usize ITEMS_TO_WRITE = 1; if (fwrite(buf, num_bytes_to_write, ITEMS_TO_WRITE, (FILE *)this->handle) == ITEMS_TO_WRITE) { - rewind((FILE *)this->handle); num_bytes_written = ITEMS_TO_WRITE * num_bytes_to_write; } #endif @@ -7781,7 +7651,7 @@ DQN_FILE_SCOPE u8 *DqnFile_ReadAll(wchar_t const *path, usize *buf_size, DqnMemS DQN_LOGE("Could not open file: %s", path); return result; } - DQN_DEFER(file.Close()); + DQN_DEFER { file.Close(); }; result = static_cast(stack->Push(file.size, push_type)); usize bytes_read = file.Read(result, file.size); @@ -7806,7 +7676,7 @@ DQN_FILE_SCOPE u8 *DqnFile_ReadAll(char const *path, usize *buf_size, DqnMemStac DQN_LOGE("Could not open file: %s", path); return result; } - DQN_DEFER(file.Close()); + DQN_DEFER { file.Close(); }; result = static_cast(stack->Push(file.size, push_type)); usize bytes_read = file.Read(result, file.size); @@ -7831,8 +7701,8 @@ DQN_FILE_SCOPE bool DqnFile_WriteAll(char const *path, u8 const *buf, usize cons return false; } - DQN_DEFER(file.Close()); - usize bytes_written = file.Write(buf, buf_size, 0); + DQN_DEFER { file.Close(); }; + usize bytes_written = file.Write(buf, buf_size); if (bytes_written != buf_size) { DQN_LOGE("Bytes written did not match the buffer size, %zu != %zu", bytes_written, buf_size); @@ -7851,8 +7721,8 @@ DQN_FILE_SCOPE bool DqnFile_WriteAll(wchar_t const *path, u8 const *buf, usize c return false; } - DQN_DEFER(file.Close()); - usize bytes_written = file.Write(buf, buf_size, 0); + DQN_DEFER { file.Close(); }; + usize bytes_written = file.Write(buf, buf_size); if (bytes_written != buf_size) { DQN_LOGE("Bytes written did not match the buffer size, %zu != %zu", bytes_written, buf_size); @@ -7866,7 +7736,7 @@ DQN_FILE_SCOPE bool DqnFile_ReadAll(wchar_t const *path, u8 *buf, usize buf_size { DqnFile file = {}; bool result = file.Open(path, DqnFile::Flag::FileRead, DqnFile::Action::OpenOnly); - DQN_DEFER(file.Close()); + DQN_DEFER { file.Close(); }; // TODO(doyle): Logging if (file.size > buf_size || !result) @@ -7884,7 +7754,7 @@ DQN_FILE_SCOPE bool DqnFile_ReadAll(char const *path, u8 *buf, usize buf_size) { DqnFile file = {}; bool result = file.Open(path, DqnFile::Flag::FileRead, DqnFile::Action::OpenOnly); - DQN_DEFER(file.Close()); + DQN_DEFER { file.Close(); }; if (!result || file.size > buf_size) { @@ -8671,10 +8541,10 @@ DQN_FILE_SCOPE void DqnWin32_OutputDebugString(char const *fmt_str, ...) OutputDebugStringA(str); } -DQN_FILE_SCOPE i32 DqnWin32_GetEXEDirectory(char *buf, u32 buf_len) +DQN_FILE_SCOPE i32 DqnWin32_GetExeDirectory(wchar_t *buf, u32 buf_len) { if (!buf || buf_len == 0) return -1; - u32 copied_len = GetModuleFileNameA(nullptr, buf, buf_len); + u32 copied_len = GetModuleFileNameW(nullptr, buf, buf_len); if (copied_len == buf_len) return -1; // NOTE: Should always work if GetModuleFileName works and we're running an diff --git a/dqn.natvis b/dqn.natvis index 48a6a19..d5a0801 100644 --- a/dqn.natvis +++ b/dqn.natvis @@ -1,27 +1,19 @@ - {{count={count}/{max}}} + {{len={len}/{max}}} - count + len max - count + len data - {{used={used}/{size} prevBlock={prevBlock}}} - - - - {{bytesAllocated={bytesAllocated} lifetimeBytesAllocated={lifetimeBytesAllocated} lifetimeBytesFreed={lifetimeBytesFreed}}} - - - - {{numEntries={numEntries} numFreeEntries={numFreeEntries} usedEntriesIndex={usedEntriesIndex}}} + {{used={head-tail}/{size} prev_block={prev_block}}} @@ -29,6 +21,16 @@ data,s + + {len={len} data={data,[len]}} + data,s + + + + {{len={len} {str,s}}} + str,s + + {{len={len}/{max} {str,s}}} str,s