diff --git a/Allocators/CMakeLists.txt b/Allocators/CMakeLists.txt deleted file mode 100644 index 8b59432..0000000 --- a/Allocators/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -project(Allocators) - -### ---------------------- Static Library --------------------- ### -file(GLOB SOURCES "./private/*.cpp") -file(GLOB HEADERS "./public/*.hpp") -add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS}) -target_include_directories(${PROJECT_NAME} PUBLIC ./public/) -target_link_libraries(${PROJECT_NAME} PUBLIC Callstack) - -### -------------------------- Tests -------------------------- ### -enable_testing() -file(GLOB TEST_SOURCES "./tests/*.cpp") -add_executable(Tests${PROJECT_NAME} ${TEST_SOURCES}) -target_link_libraries(Tests${PROJECT_NAME} ${PROJECT_NAME} UnitTest++) -add_test(NAME Tests${PROJECT_NAME} COMMAND Tests${PROJECT_NAME}) \ No newline at end of file diff --git a/Allocators/README.md b/Allocators/README.md deleted file mode 100644 index d2beeba..0000000 --- a/Allocators/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Profiling - -## Memory Leaks - -Example program with memory leaks: - -```c++ -#include "allocators.h" - -void test_call22() { new int; } -void test_call21() { new float; } - -void test_call11() { - test_call21(); - test_call22(); -} - -int main(char argc, char* argv[]) { - tp::ModuleManifest* ModuleDependencies[] = { &tp::gModuleAllocators, NULL }; - tp::ModuleManifest TestModule("Test", NULL, NULL, ModuleDependencies); - TestModule.initialize(); - - test_call11(); - - TestModule.deinitialize(); -} - -``` -If memory leaks were detected it will be logged in the output console. - -![image](https://user-images.githubusercontent.com/63184036/222794298-3f238de4-c0b8-41fa-b7ec-c0c675da8f05.png) - -Also debug.memleaks binary will be generated in the working directory that can be viewed with MemLeaks Viewer. - -![image](https://user-images.githubusercontent.com/63184036/222793169-a405effe-72be-42fc-b375-bb06dce0a735.png) - diff --git a/Allocators/private/Allocators.cpp b/Allocators/private/Allocators.cpp deleted file mode 100644 index ab98472..0000000 --- a/Allocators/private/Allocators.cpp +++ /dev/null @@ -1,21 +0,0 @@ - -#include "Allocators.hpp" -#include "HeapAllocatorGlobal.hpp" - -#include -#include - -void* operator new(size_t aSize) { return tp::HeapAllocGlobal::allocate(aSize); } -void* operator new[](size_t aSize) { return tp::HeapAllocGlobal::allocate(aSize); } -void operator delete(void* aPtr) noexcept { tp::HeapAllocGlobal::deallocate(aPtr); } -void operator delete[](void* aPtr) noexcept { tp::HeapAllocGlobal::deallocate(aPtr); } - -void* operator new(size_t aSize, tp::HeapAlloc& aAlloc) { return aAlloc.allocate(aSize); } -void* operator new[](size_t aSize, tp::HeapAlloc& aAlloc) { return aAlloc.allocate(aSize); } -void operator delete(void* aPtr, tp::HeapAlloc& aAlloc) { aAlloc.deallocate(aPtr); } -void operator delete[](void* aPtr, tp::HeapAlloc& aAlloc) { aAlloc.deallocate(aPtr); } - -void* operator new(size_t aSize, tp::HeapAllocGlobal& aAlloc) { return tp::HeapAllocGlobal::allocate(aSize); } -void* operator new[](size_t aSize, tp::HeapAllocGlobal& aAlloc) { return tp::HeapAllocGlobal::allocate(aSize); } -void operator delete(void* aPtr, tp::HeapAllocGlobal& aAlloc) { tp::HeapAllocGlobal::deallocate(aPtr); } -void operator delete[](void* aPtr, tp::HeapAllocGlobal& aAlloc) { tp::HeapAllocGlobal::deallocate(aPtr); } \ No newline at end of file diff --git a/Allocators/private/HeapAllocator.cpp b/Allocators/private/HeapAllocator.cpp deleted file mode 100644 index f4e1cdf..0000000 --- a/Allocators/private/HeapAllocator.cpp +++ /dev/null @@ -1,76 +0,0 @@ - - -#include "HeapAllocator.hpp" -#include "HeapAllocatorGlobal.hpp" - -#include "PrivateConfig.hpp" - -#include - -using namespace tp; - -#if not defined(MEM_DEBUG) - -// ----------------------- Release Implementation ---------------------------- // -void* HeapAlloc::allocate(ualni aBlockSize) { return malloc(aBlockSize); } -void HeapAlloc::deallocate(void* aPtr) { - if (!aPtr) return; - free(aPtr); -} -HeapAlloc::~HeapAlloc() {} - -#else - -namespace tp { - struct MemHeadLocal { - MemHeadLocal* mPrev; - MemHeadLocal* mNext; - }; -} - -void* HeapAlloc::allocate(ualni aBlockSize) { - auto head = (MemHeadLocal*) HeapAllocGlobal::allocate(aBlockSize + sizeof(MemHeadLocal)); - auto out = head + 1; - - mNumAllocations++; - if (mEntry) { - DEBUG_ASSERT(!mEntry->mNext); - head->mNext = nullptr; - head->mPrev = mEntry; - mEntry->mNext = head; - } else { - head->mNext = nullptr; - head->mPrev = nullptr; - } - mEntry = head; - - return out; -} - -void HeapAlloc::deallocate(void* aPtr) { - if (!aPtr) return; - - auto head = ((MemHeadLocal*) (aPtr)) - 1; - - mNumAllocations--; - DEBUG_ASSERT(!mEntry->mNext); - if (head->mNext) head->mNext->mPrev = head->mPrev; - if (head->mPrev) head->mPrev->mNext = head->mNext; - if (head == mEntry) { - mEntry = head->mPrev; - } - - HeapAllocGlobal::deallocate(head); -} - -HeapAlloc::~HeapAlloc() { - if (mNumAllocations) { - DEBUG_ASSERT(0 && "Destruction of not freed Allocator"); - -#ifdef MEM_STACK_TRACE - // TODO : log leaks and free them up -#endif - } -} - -#endif diff --git a/Allocators/private/HeapAllocatorGlobal.cpp b/Allocators/private/HeapAllocatorGlobal.cpp deleted file mode 100644 index 9d2a76e..0000000 --- a/Allocators/private/HeapAllocatorGlobal.cpp +++ /dev/null @@ -1,232 +0,0 @@ - - -#include "HeapAllocatorGlobal.hpp" -#include "PrivateConfig.hpp" - -#include "AllocatorsTypes.hpp" -// #include "Callstack.hpp" - -#include -#include - -using namespace tp; - -#if not defined(MEM_DEBUG) - -// ----------------------- Release Implementation ---------------------------- // - -void* HeapAllocGlobal::allocate(ualni aBlockSize) { return malloc(aBlockSize); } -void HeapAllocGlobal::deallocate(void* aPtr) { - if (!aPtr) return; - free(aPtr); -} -HeapAllocGlobal::~HeapAllocGlobal() = default; -bool HeapAllocGlobal::checkLeaks() { return false; } -void HeapAllocGlobal::startIgnore() {} -void HeapAllocGlobal::stopIgnore() {} -ualni HeapAllocGlobal::getNAllocations() { return 0; } - -#else - -tp::MemHead* tp::HeapAllocGlobal::mEntry = nullptr; -tp::ualni tp::HeapAllocGlobal::mNumAllocations = 0; -std::mutex tp::HeapAllocGlobal::mMutex; -bool tp::HeapAllocGlobal::mIgnore = true; -bool tp::HeapAllocGlobal::mEnableCallstack = true; - -#ifdef MEM_STACK_TRACE -tp::CallStackCapture tp::HeapAllocGlobal::mCallstack; -#endif - - // ----------------------- Debug Implementation ---------------------------- // -// |----------------| -// | MemHead | -// |----------------| -// | wrap top | -// |----------------| - Allocated Block Layout -// | data | -// |----------------| -// | wrap bottom | -// |----------------| - -namespace tp { - struct MemHead { - MemHead* mPrev; - MemHead* mNext; - uhalni mBlockSize; - uhalni mIgnored; -#ifdef MEM_STACK_TRACE - const CallStackCapture::CallStack* mCallStack; -#else - void* p; -#endif - }; -} - -enum : ualni { - ALIGNED_SIZE = ENV_ALNI_SIZE_B, - WRAP_SIZE = MEM_WRAP_SIZE * ALIGNED_SIZE, - WRAP_VAL = MEM_WRAP_FILL_VAL, - HEAD_SIZE = sizeof(MemHead), - CLEAR_ALLOC_VAL = MEM_CLEAR_ON_ALLOC_VAL, - CLEAR_DEALLOC_VAL = MEM_CLEAR_ON_DEALLOC_VAL, -}; - -void* HeapAllocGlobal::allocate(ualni aBlockSize) { - - static_assert(HEAD_SIZE % ALIGNED_SIZE == 0, "Heap Allocator Configuration Error"); - - if (aBlockSize % ALIGNED_SIZE) { - aBlockSize = (aBlockSize / ALIGNED_SIZE + 1) * ALIGNED_SIZE; - } - -// 1) Allocate the block -ALLOCATE: - auto head = (MemHead*) malloc(aBlockSize + WRAP_SIZE * 2 + HEAD_SIZE); - if (!head) { - printf("WARNING : Cant allocate memory. Trying again\n"); - goto ALLOCATE; // Just freeze if no memory is available - } - - auto wrap_top = (int1*) (head + 1); - auto data = wrap_top + WRAP_SIZE; - auto wrap_bottom = data + aBlockSize; - - head->mBlockSize = aBlockSize; - head->mIgnored = mIgnore; - - // 2) Link with existing blocks - mMutex.lock(); - mNumAllocations++; - if (mEntry) { - DEBUG_ASSERT(mEntry->mNext == nullptr); - head->mNext = nullptr; - head->mPrev = mEntry; - mEntry->mNext = head; - } else { - head->mNext = nullptr; - head->mPrev = nullptr; - } - mEntry = head; - - // 3) Trace the stack -#ifdef MEM_STACK_TRACE - // check if somewhat decides to call new within static variable initialization - head->mCallStack = (mEnableCallstack && mCallstack.initialized) ? mCallstack.getSnapshot() : nullptr; -#endif - - mMutex.unlock(); - - // 4) Wrap fill - memSetVal(wrap_top, WRAP_SIZE, WRAP_VAL); - memSetVal(wrap_bottom, WRAP_SIZE, WRAP_VAL); - - // 5) clear data -#ifdef MEM_CLEAR_ON_ALLOC - memSetVal(data, aBlockSize, CLEAR_ALLOC_VAL); -#endif - - return data; -} - -void HeapAllocGlobal::deallocate(void* aPtr) { - if (!aPtr) return; - - // 1) Restore the pointers - auto head = ((MemHead*) ((int1*) aPtr - WRAP_SIZE)) - 1; - auto wrap_top = (int1*) (head + 1); - auto data = wrap_top + WRAP_SIZE; - auto wrap_bottom = data + head->mBlockSize; - - // 2) Unlink with blocks - mMutex.lock(); - mNumAllocations--; - DEBUG_ASSERT(!mEntry->mNext); - if (head->mNext) head->mNext->mPrev = head->mPrev; - if (head->mPrev) head->mPrev->mNext = head->mNext; - if (head == mEntry) { - mEntry = head->mPrev; - } - - if (!head->mIgnored) { - // 3) Check the wrap - if (memCompareVal(wrap_top, WRAP_SIZE, WRAP_VAL)) { -#ifdef MEM_STACK_TRACE - if (head->mCallStack) mCallstack.printSnapshot(head->mCallStack); -#endif - ASSERT(!"Allocated Block Wrap Corrupted!"); - } - - if (memCompareVal(wrap_bottom, WRAP_SIZE, WRAP_VAL)) { -#ifdef MEM_STACK_TRACE - if (head->mCallStack) mCallstack.printSnapshot(head->mCallStack); -#endif - ASSERT(!"Allocated Block Wrap Corrupted!"); - } - - // 4) clear data -#ifdef MEM_CLEAR_ON_ALLOC - memSetVal(data, head->mBlockSize, CLEAR_DEALLOC_VAL); -#endif - } - - mMutex.unlock(); - - // 5) free the block - free(head); -} - -bool HeapAllocGlobal::checkLeaks() { - ualni ignoredCount = 0; - for (auto iter = mEntry; iter; iter = iter->mPrev) { - ignoredCount += iter->mIgnored; - } - - // 1) Check for not deallocated memory - if (mNumAllocations && ignoredCount < mNumAllocations) { - -#ifdef MEM_STACK_TRACE - for (auto iter = mEntry; iter; iter = iter->mPrev) { - if (!iter->mIgnored && iter->mCallStack) mCallstack.printSnapshot(iter->mCallStack); - } -#endif - - printf(" Count : %llu", mNumAllocations - ignoredCount); - - ASSERT(!"Destruction of not freed Allocator"); - return true; - } - return false; -} - -void HeapAllocGlobal::startIgnore() { - mMutex.lock(); - mIgnore = true; - mMutex.unlock(); -} - -void HeapAllocGlobal::stopIgnore() { - mMutex.lock(); - mIgnore = false; - mMutex.unlock(); -} - -ualni HeapAllocGlobal::getNAllocations() { - return mNumAllocations; -} - -void HeapAllocGlobal::enableCallstack() { - mMutex.lock(); - mEnableCallstack = true; - mMutex.unlock(); -} - -void HeapAllocGlobal::disableCallstack() { - mMutex.lock(); - mEnableCallstack = false; - mMutex.unlock(); -} - -HeapAllocGlobal::~HeapAllocGlobal() = default; - -#endif diff --git a/Allocators/public/Allocators.hpp b/Allocators/public/Allocators.hpp deleted file mode 100644 index b03dd39..0000000 --- a/Allocators/public/Allocators.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "AllocatorsTypes.hpp" - -#include "ChunkAllocator.hpp" -#include "HeapAllocator.hpp" -#include "HeapAllocatorGlobal.hpp" -#include "PoolAllocator.hpp" - -void* operator new(std::size_t aSize); -void* operator new[](std::size_t aSize); -void operator delete(void* aPtr) noexcept; -void operator delete[](void* aPtr) noexcept; - -void* operator new(std::size_t aSize, tp::HeapAlloc& aAlloc); -void* operator new[](std::size_t aSize, tp::HeapAlloc& aAlloc); -void operator delete(void* aPtr, tp::HeapAlloc& aAlloc); -void operator delete[](void* aPtr, tp::HeapAlloc& aAlloc); - -void* operator new(std::size_t aSize, tp::HeapAllocGlobal& aAlloc); -void* operator new[](std::size_t aSize, tp::HeapAllocGlobal& aAlloc); -void operator delete(void* aPtr, tp::HeapAllocGlobal& aAlloc); -void operator delete[](void* aPtr, tp::HeapAllocGlobal& aAlloc); \ No newline at end of file diff --git a/Allocators/public/AllocatorsTypes.hpp b/Allocators/public/AllocatorsTypes.hpp deleted file mode 100644 index 5d9dd23..0000000 --- a/Allocators/public/AllocatorsTypes.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#include "Environment.hpp" -#include "Utils.hpp" diff --git a/Allocators/public/ChunkAllocator.hpp b/Allocators/public/ChunkAllocator.hpp deleted file mode 100644 index 6f20eb8..0000000 --- a/Allocators/public/ChunkAllocator.hpp +++ /dev/null @@ -1,136 +0,0 @@ -#pragma once - -/* -* Implementation uses embedded one-directional linked list to track free blocks. -* The embedded part ensures that there is no memory overhead on block specifically. -* Linked list is initialized iteratively on each allocation if it has not been already. - -* Allocating: -* 1) updating list entry to stored in the entry itself next free pointer -* 2) returning entry before (1). -* -* Deallocating: -* 1) assigning list entry value to the deleted block -* 2) updating list entry to that block. -*/ - -#include "AllocatorsTypes.hpp" -#include "HeapAllocatorGlobal.hpp" -#include "PrivateConfig.hpp" - -namespace tp { - - // Chunk Allocator - // Constant time allocations and de-allocations in any order. - // Memory blocks are fixed in size and number of blocks can not exceed given parameter. - template - class ChunkAlloc { - - enum : ualni { - ALIGNED_SIZE = ENV_ALNI_SIZE_B, - - WRAP_SIZE_ALN = MEM_WRAP_SIZE / 2, - WRAP_SIZE = WRAP_SIZE_ALN * ALIGNED_SIZE, - - WRAP_VAL = MEM_WRAP_FILL_VAL, - CLEAR_ALLOC_VAL = MEM_CLEAR_ON_ALLOC_VAL, - CLEAR_DEALLOC_VAL = MEM_CLEAR_ON_DEALLOC_VAL, - }; - - static constexpr ualni dataSize() { - auto BLOCK_SIZE_BYTES = sizeof(tType); - auto BLOCK_SIZE_ALIGNED = BLOCK_SIZE_BYTES / ALIGNED_SIZE; - return BLOCK_SIZE_ALIGNED; - } - - static constexpr ualni blockSize() { - auto BLOCK_SIZE_BYTES = sizeof(tType); - auto BLOCK_SIZE = dataSize() + bool(BLOCK_SIZE_BYTES % ALIGNED_SIZE) + WRAP_SIZE_ALN * 2; - return BLOCK_SIZE; - } - - private: - ualni* mNextBlock; - ualni mNumFreeBlocks; - ualni mNumInitBlocks; - ualni mBuff[tNumBlocks * blockSize() * ALIGNED_SIZE]; - - public: - ChunkAlloc() { - mNumFreeBlocks = tNumBlocks; - mNumInitBlocks = 0; - mNextBlock = mBuff; - } - - ~ChunkAlloc() = default; // TODO : check for leaks - - public: - void* allocate(ualni) { - DEBUG_ASSERT(mNumFreeBlocks && "Out Of Memory"); - - // 1) PreInitialize blocks - if (mNumInitBlocks < tNumBlocks) { - mBuff[mNumInitBlocks * blockSize()] = (ualni) (mBuff + (mNumInitBlocks + 1) * blockSize()); - mNumInitBlocks++; - } - - // 2) Find free block and update next free block - auto data = mNextBlock; - mNextBlock = (ualni*) (*data); - mNumFreeBlocks--; - -#ifdef MEM_DEBUG - // 3) Fill Wrap and offset data - auto wrap_top = data; - auto wrap_bottom = data + WRAP_SIZE_ALN + dataSize(); - - memSetVal(wrap_top, WRAP_SIZE, WRAP_VAL); - memSetVal(wrap_bottom, WRAP_SIZE, WRAP_VAL); - -// 4) Clear data -#ifdef MEM_CLEAR_ON_ALLOC - memSetVal(data + WRAP_SIZE_ALN, dataSize() * ALIGNED_SIZE, CLEAR_ALLOC_VAL); -#endif - - data += WRAP_SIZE_ALN; -#endif - - return data; - } - - void deallocate(void* aPtr) { - DEBUG_ASSERT(aPtr >= mBuff && aPtr < mBuff + tNumBlocks * blockSize()); - - auto block = (ualni*) aPtr; - -#ifdef MEM_DEBUG - // 3) Check Wrap and offset data - auto wrap_bottom = block + dataSize(); - auto wrap_top = block - WRAP_SIZE_ALN; - block = wrap_top; - - // 3) Check the wrap - ASSERT(!memCompareVal(wrap_top, WRAP_SIZE, WRAP_VAL) && "Allocated Block Wrap Corrupted!"); - ASSERT(!memCompareVal(wrap_bottom, WRAP_SIZE, WRAP_VAL) && "Allocated Block Wrap Corrupted!"); - -// 4) Clear data -#ifdef MEM_CLEAR_ON_ALLOC - memSetVal(block, blockSize() * ALIGNED_SIZE, CLEAR_DEALLOC_VAL); -#endif - -#endif - - (*block) = (ualni) mNextBlock; - mNextBlock = block; - mNumFreeBlocks++; - } - - [[nodiscard]] bool checkWrap() const { return false; } - void checkValid() {} - - public: - [[nodiscard]] bool isFull() const { return !mNumFreeBlocks; } - [[nodiscard]] bool isEmpty() const { return mNumFreeBlocks == tNumBlocks; } - [[nodiscard]] const ualni* getBuff() const { return mBuff; } - }; -} \ No newline at end of file diff --git a/Allocators/public/HeapAllocator.hpp b/Allocators/public/HeapAllocator.hpp deleted file mode 100644 index d51035f..0000000 --- a/Allocators/public/HeapAllocator.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "AllocatorsTypes.hpp" - -namespace tp { - - class HeapAlloc { - -#ifdef MEM_DEBUG - ualni mNumAllocations = 0; - struct MemHeadLocal* mEntry = nullptr; -#endif - - public: - HeapAlloc() = default; - ~HeapAlloc(); - - public: - void* allocate(ualni aBlockSize); - void deallocate(void* aPtr); - - public: - [[nodiscard]] bool checkWrap() const { return false; } - void checkValid() {} - }; -} diff --git a/Allocators/public/HeapAllocatorGlobal.hpp b/Allocators/public/HeapAllocatorGlobal.hpp deleted file mode 100644 index d32a377..0000000 --- a/Allocators/public/HeapAllocatorGlobal.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "AllocatorsTypes.hpp" - -// #include "Callstack.hpp" - -#include - -namespace tp { - - class HeapAllocGlobal { - -#ifdef MEM_DEBUG - static ualni mNumAllocations; - static struct MemHead* mEntry; - static std::mutex mMutex; - static bool mIgnore; - static bool mEnableCallstack; -#ifdef MEM_STACK_TRACE // Save stack on allocation call - static CallStackCapture mCallstack; -#endif -#endif - - public: - HeapAllocGlobal() = default; - ~HeapAllocGlobal(); - - public: - static void* allocate(ualni aBlockSize); - static void deallocate(void* aPtr); - - static bool checkLeaks(); - static void startIgnore(); - static void stopIgnore(); - static ualni getNAllocations(); - - static void enableCallstack(); - static void disableCallstack(); - - public: - [[nodiscard]] bool checkWrap() const { return false; } - void checkValid() {} - }; -} diff --git a/Allocators/public/PoolAllocator.hpp b/Allocators/public/PoolAllocator.hpp deleted file mode 100644 index 1b53267..0000000 --- a/Allocators/public/PoolAllocator.hpp +++ /dev/null @@ -1,161 +0,0 @@ -#pragma once - -/* -Implementation: -* Adding chunk pointer to each chunk to form one-directional list that keeps track of free chunk -* Storing ordered pointers to chunks in order to find desired chunk from delete pointer on de-allocation in log time -* -* Allocations: -* 1) allocate with chunk stored in list entry -* 2) ... -* -* De-allocations: -* 1) binary-search with delete pointer to find desired chunk -* 2) ... -* -*/ - -#include "ChunkAllocator.hpp" - -namespace tp { - - // Pool Allocator - // Overcomes chunk allocator fixed number of max allocations - template - class PoolAlloc { - - typedef ChunkAlloc Chunk; - - struct Chunks { - - void add(Chunk* aChunk) { - - if (!mBuff) { - mLen = 16; - mBuff = (Chunk**) HeapAllocGlobal::allocate(sizeof(Chunk*) * mLen); - mUsedLen = 1; - mBuff[0] = aChunk; - return; - } - - // ensure order - auto smaller_address = findUtil(mBuff, mBuff + mUsedLen, aChunk); - for (auto iter = mBuff + mUsedLen; iter != smaller_address; iter--) { - *iter = *(iter - 1); - } - - *(smaller_address) = aChunk; - mUsedLen++; - - // check for buff overflow - if (mUsedLen == mLen) { - auto prevBuff = mBuff; - mBuff = (Chunk**) HeapAllocGlobal::allocate(sizeof(Chunk*) * mLen * 2); - memCopy(mBuff, prevBuff, sizeof(Chunk*) * mUsedLen); - mLen *= 2; - HeapAllocGlobal::deallocate(prevBuff); - } - } - - void remove(Chunk** del_address) { - if (mUsedLen == 1) { - mLen = 0; - mUsedLen = 0; - HeapAllocGlobal::deallocate(mBuff); - mBuff = nullptr; - return; - } - - // ensure order - for (auto iter = del_address; iter != mBuff + mUsedLen - 1; iter++) { - *iter = *(iter + 1); - } - - mUsedLen--; - - // check for buff low usage - if ((halnf) mUsedLen / (halnf) mLen < 0.25f) { - auto prevBuff = mBuff; - mBuff = (Chunk**) HeapAllocGlobal::allocate(sizeof(Chunk*) * mLen / 2); - memCopy(mBuff, prevBuff, sizeof(Chunk*) * mUsedLen); - mLen /= 2; - HeapAllocGlobal::deallocate(prevBuff); - } - } - - [[nodiscard]] Chunk** find(void* aPtr) { return findUtil(mBuff, mBuff + mUsedLen, aPtr) - 1; } - - [[nodiscard]] Chunk* findNotFull() const { - for (ualni idx = 0; idx < mUsedLen; idx++) { - if (!mBuff[idx]->isFull()) { - return mBuff[idx]; - } - } - return nullptr; - } - - Chunk** mBuff = nullptr; - ualni mUsedLen = 0; - ualni mLen = 0; - - private: - Chunk** findUtil(Chunk** aLeft, Chunk** aRight, void* aPtr) { - auto range = ualni(aRight - aLeft); - if (range == 1) { - return (aPtr < *aLeft) ? aLeft : aRight; - } - auto middle = aLeft + range / 2; - return (aPtr >= (*middle)) ? findUtil(middle, aRight, aPtr) : findUtil(aLeft, middle, aPtr); - } - }; - - private: - Chunks mChunks; - Chunk* mFreeChunk = nullptr; - - public: - PoolAlloc() = default; - ~PoolAlloc() = default; - - public: - void* allocate(ualni) { - if (!mFreeChunk || mFreeChunk->isFull()) { - auto new_free_chunk = mChunks.findNotFull(); - if (!new_free_chunk) { - new_free_chunk = new (HeapAllocGlobal::allocate(sizeof(Chunk))) Chunk(); - DEBUG_ASSERT(new_free_chunk); - mChunks.add(new_free_chunk); - } - mFreeChunk = new_free_chunk; - } - return mFreeChunk->allocate(0); - } - - void deallocate(void* aPtr) { - if (!aPtr) return; - auto chunk = mChunks.find(aPtr); - (*chunk)->deallocate(aPtr); - if ((*chunk)->isEmpty()) { - if (mFreeChunk == *chunk) mFreeChunk = nullptr; - HeapAllocGlobal::deallocate(*chunk); - mChunks.remove(chunk); - } - } - - public: - [[nodiscard]] bool checkWrap() const { return false; } - - void checkValid() { - return; - for (auto i = 0; i < mChunks.mUsedLen; i++) { - for (auto j = 0; j < mChunks.mUsedLen; j++) { - if (i > j) { - ASSERT(mChunks.mBuff[i] > mChunks.mBuff[j]); - } else if (i < j) { - ASSERT(mChunks.mBuff[i] < mChunks.mBuff[j]); - } - } - } - } - }; -} diff --git a/Allocators/public/PrivateConfig.hpp b/Allocators/public/PrivateConfig.hpp deleted file mode 100644 index e8d735e..0000000 --- a/Allocators/public/PrivateConfig.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#define MEM_WRAP_SIZE 8 // Wrapping Size in aligned units -#define MEM_WRAP_FILL_VAL 0xBB // Wrapping Fill Value -#define MEM_CLEAR_ON_ALLOC // Clear data on allocation -#define MEM_CLEAR_ON_DEALLOC // Clear data on free -#define MEM_CLEAR_ON_DEALLOC_VAL 0xAA // Clear data on free -#define MEM_CLEAR_ON_ALLOC_VAL 0xCC // Clear data on free -#define MEM_STACK_TRACE_MAX_DEPTH 32 // Call stack max depth \ No newline at end of file diff --git a/Allocators/tests/Test.cpp b/Allocators/tests/Test.cpp deleted file mode 100644 index 4b0563d..0000000 --- a/Allocators/tests/Test.cpp +++ /dev/null @@ -1,249 +0,0 @@ - -#include "UnitTest++/UnitTest++.h" - -#include "Allocators.hpp" -#include "Utils.hpp" - -#include - -using namespace tp; - -struct TestStruct { - alni val = 0; - - TestStruct() : - val(0) {} - explicit TestStruct(alni val) : - val(val) {} - TestStruct(const TestStruct& in) : - val(in.val) {} - - ~TestStruct() { val = -1; } - - bool operator==(const TestStruct& in) const { return in.val == val; } -}; - -template -class TestBenches { - - tAllocator mAlloc{}; - TestStruct mData[tSize]{}; - TestStruct* mLoaded[tSize]{}; - bool mIsLoaded[tSize]{}; - alni mLoadedNum = 0; - -public: - TestBenches() { - for (alni i = 0; i < tSize; i++) { - mData[i].val = i; - mIsLoaded[i] = false; - mLoaded[i] = nullptr; - } - } - - void runTests() { - try { - test1(); - test2(); - test3(); - test4(); - test5(); - test6(); - } catch (...) { - ASSERT(false) - } - } - -private: - alni randomIdx(bool state, Range range = { 0, tSize }) { - RAND: - auto idx = alni(alnf(range.idxBegin()) + randomFloat() * alnf(range.idxDiff() + 1)); - idx = clamp(idx, alni(0), tSize - 1); - if (state == mIsLoaded[idx]) goto RAND; - return idx; - } - - void verifyIntegrity() { - mAlloc.checkValid(); - ASSERT(!mAlloc.checkWrap()) - for (alni i = 0; i < tSize; i++) { - if (mIsLoaded[i]) { - ASSERT(*mLoaded[i] == mData[i]) - } - } - } - - void loadItem(alni idx) { - if (mIsLoaded[idx]) return; - verifyIntegrity(); - mLoaded[idx] = new (mAlloc.allocate(sizeof(TestStruct))) TestStruct(mData[idx]); - ASSERT(mLoaded[idx]); - mIsLoaded[idx] = true; - mLoadedNum++; - verifyIntegrity(); - } - - void unloadItem(alni idx) { - if (!mIsLoaded[idx]) return; - verifyIntegrity(); - mLoaded[idx]->~TestStruct(); - mAlloc.deallocate(mLoaded[idx]); - mIsLoaded[idx] = false; - mLoadedNum--; - verifyIntegrity(); - } - - void changeStates(Range rg, bool load, bool reversed = false, bool random = false) { - for (auto i : rg) { - alni idx = i; - if (random) { - idx = randomIdx(load, rg); - } else if (reversed) { - idx = rg.idxEnd() - i - 1; - } - (load) ? loadItem(idx) : unloadItem(idx); - } - } - - // full down-up load then up-down unload - void test1() { - changeStates({ 0, tSize }, true); - changeStates({ 0, tSize }, false, true); - } - - // full down-up load then down-up unload - void test2() { - changeStates({ 0, tSize }, true); - changeStates({ 0, tSize }, false); - } - - // full random load then random unload - void test3() { - changeStates({ 0, tSize }, true, false, true); - changeStates({ 0, tSize }, false, false, true); - } - - // combo tests 1-3 - void test4() { - test1(); - test1(); - - test2(); - test2(); - - test3(); - test3(); - } - - static alnf sineUpFunction(alnf aSize, alnf aX, bool aReverse) { - alnf end = 4 * 3.14159; - alnf a = (2 / 7.f) * aSize; - alnf b = end / aSize; - - alni c = ((-1 * aReverse) + (1 * !aReverse)); - alnf c1 = (aX - (end * aReverse)) / b; - alnf c2 = (a * sin(aX - (end * aReverse))); - alnf out = c1 + c2; - return (alnf) c * out; - } - - // sin load & sin unload with ~1/2 drop factor - void test5() { - alnf end = 4 * 3.14159; - alnf step = end / 4.f; - - for (char i = 0; i < 2; i++) { - for (alnf x = 0; x <= end; x += step) { - - alni target_alloc_count = (alni) ceil(sineUpFunction(tSize, x, i)); - target_alloc_count = clamp(target_alloc_count, alni(0), tSize); - - while (mLoadedNum > target_alloc_count) { - unloadItem(randomIdx(0)); - } - while (mLoadedNum < target_alloc_count) { - loadItem(randomIdx(1)); - } - } - } - } - - void checkWrap(ualni offset, bool after) { - offset = clamp(offset, (ualni) 1, (ualni) MEM_WRAP_SIZE); - - TestStruct* ts = mLoaded[randomIdx(0)]; - ualni shift = (sizeof(TestStruct) * after) + (offset - 1) * after - offset * (!after); - uint1* address = (((uint1*) ts) + shift); - - uint1 val = *address; - *address = 5; - - ASSERT(!mAlloc.checkWrap()); - - *address = val; - } - - // mem guards test - void test6() { - changeStates({ 0, tSize }, 1); -#ifdef MEM_DEBUG - for (alni after = 0; after < 2; after++) { - for (alni offset = 1; offset <= MEM_WRAP_SIZE; offset++) { - checkWrap(offset, after); - } - } -#endif - changeStates({ 0, tSize }, 0); - } -}; - -const ualni size = 500; - -template -void testAlloc() { - try { - TestBenches heapTests{}; - heapTests.runTests(); - } catch (...) { - ASSERT(false); - } -} - -SUITE(Allocators) { - TEST(GlobalHeap) { testAlloc(); } - - TEST(Heap) { testAlloc(); } - - TEST(Chunk) { - testAlloc>(); - testAlloc>(); - } - - TEST(Pool) { - testAlloc>(); - testAlloc>(); - testAlloc>(); - } - - TEST(Simple) { - auto a = new TestStruct(-1); - delete a; - } -} - - -int main() { - - tp::ModuleManifest* deps[] = { &tp::gModuleAllocators, nullptr }; - tp::ModuleManifest testModule("AllocatorsTest", nullptr, nullptr, deps); - - if (!testModule.initialize()) { - return 1; - } - - bool res = UnitTest::RunAllTests(); - - testModule.deinitialize(); - - return res; -} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f257cd..bf93755 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,27 +12,24 @@ include(cmake/ModulesOptions.txt) set(WINDOWS_LIBRARIES "../moduleswindowsl" CACHE STRING "Svn repository with windows libraries https://svn.riouxsvn.com/moduleswindowsl") -#include(cmake/FindGLEW.cmake) -#include(cmake/FindOIDN.cmake) -#include(cmake/FindPortAudio.cmake) +include(cmake/FindGLEW.cmake) +include(cmake/FindOIDN.cmake) +include(cmake/FindPortAudio.cmake) -#add_subdirectory(Externals) +add_subdirectory(Externals) add_subdirectory(Modules) -add_subdirectory(Callstack) -add_subdirectory(Allocators) - -#add_subdirectory(Containers) -#add_subdirectory(Math) +add_subdirectory(Containers) +add_subdirectory(Math) # add_subdirectory(Language) -#add_subdirectory(Connection) -#add_subdirectory(Graphics) -#add_subdirectory(DataAnalysis) -#add_subdirectory(Objects) -#add_subdirectory(Widgets) -#add_subdirectory(LibraryViewer) -#add_subdirectory(RasterRender) -#add_subdirectory(3DScene) -#add_subdirectory(RayTracer) -#add_subdirectory(Sketch3D) -#add_subdirectory(3DEditor) +add_subdirectory(Connection) +add_subdirectory(Graphics) +add_subdirectory(DataAnalysis) +add_subdirectory(Objects) +add_subdirectory(Widgets) +add_subdirectory(LibraryViewer) +add_subdirectory(RasterRender) +add_subdirectory(3DScene) +add_subdirectory(RayTracer) +add_subdirectory(Sketch3D) +add_subdirectory(3DEditor) diff --git a/Callstack/CMakeLists.txt b/Callstack/CMakeLists.txt deleted file mode 100644 index fc7035c..0000000 --- a/Callstack/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -project(Callstack) - -### ---------------------- Static Library --------------------- ### -file(GLOB SOURCES "./private/*.cpp") - -add_library(${PROJECT_NAME} STATIC ${SOURCES}) -target_include_directories(${PROJECT_NAME} PUBLIC ./public/) -target_link_libraries(${PROJECT_NAME} PUBLIC Modules) - -### -------------------------- Tests -------------------------- ### -file(GLOB TEST_SOURCES "./tests/*.cpp") -add_executable(Tests${PROJECT_NAME} ${TEST_SOURCES}) -target_link_libraries(Tests${PROJECT_NAME} ${PROJECT_NAME} UnitTest++) -add_test(NAME Tests${PROJECT_NAME} COMMAND Tests${PROJECT_NAME}) \ No newline at end of file diff --git a/Callstack/private/Callstack.cpp b/Callstack/private/Callstack.cpp deleted file mode 100644 index 4897748..0000000 --- a/Callstack/private/Callstack.cpp +++ /dev/null @@ -1,338 +0,0 @@ - -#include "Callstack.hpp" - -#include - -using namespace tp; - -// frame to reference on no sapce left -static void errorNoSpaceLeft() { - // to disable optimization of function - static int dummy; - dummy = 10; -} - -ualni CallStackCapture::CallStack::getDepth() const { - ualni len = 0; - for (long long frame : frames) { - if (!frame) { - break; - } - len++; - } - return len++; -} - -ualni CallStackCapture::hashCallStack(CallStackKey key) { - auto const cs = key.cs; - ualni out = 0; - for (ualni i = 0; cs->frames[i]; i++) { - out += cs->frames[i]; - } - return out; -} - -bool CallStackCapture::CallStackKey::operator==(const CallStackCapture::CallStackKey& in) const { - for (ualni i = 0; i < MAX_CALL_DEPTH_CAPTURE; i++) { - if (cs->frames[i] != in.cs->frames[i]) { - return false; - } - if (cs->frames[i] == 0 && in.cs->frames[i] == 0) { - return true; - } - } - DEBUG_ASSERT(0 && "Must Not Happen") - return true; -} - -CallStackCapture::CallStackCapture() { - static_assert(MAX_CALL_DEPTH_CAPTURE >= 1); - static_assert(MAX_CALL_CAPTURES_MEM_SIZE_MB > 0); - static_assert(MAX_DEBUG_INFO_LEN > sizeof("unresolved")); - static_assert(MAX_CALL_CAPTURES_MEM_SIZE_MB * 1024 * 1024 > sizeof(CallStack)); - - mBuffLoad = 0; - mBuffLen = STACKS_LENGTH; - mBuff = (CallStack*) malloc(mBuffLen * sizeof(CallStack)); - - mErrorSnapshot.frames[0] = (alni) & errorNoSpaceLeft; - - - platformInit(); - - initialized = true; -} - -const CallStackCapture::CallStack* CallStackCapture::getSnapshot() { - - if (mBuffLoad > mBuffLen) { - return &mErrorSnapshot; - } - - CallStack* cs = &mBuff[mBuffLoad]; - - platformWriteStackTrace(cs); - - auto idx = mSnapshots.presents({ cs }); - if (idx) { - return mSnapshots.getSlotVal(idx); - } - - mSnapshots.put({ cs }, cs); - - mBuffLoad++; - return cs; -} - -const CallStackCapture::DebugSymbols* CallStackCapture::getSymbols(FramePointer frame) { - auto idx = mSymbols.presents(frame); - if (idx) { - return &mSymbols.getSlotVal(idx); - } - - mSymbols.put(frame, {}); - auto symbols = &mSymbols.get(frame); - - platformWriteDebugSymbols(frame, symbols); - return symbols; -} - -void CallStackCapture::clear() { - mBuffLoad = 0; - mSnapshots.removeAll(); - mSymbols.removeAll(); -} - -CallStackCapture::~CallStackCapture() { - free(mBuff); - initialized = false; -} - -// ---------------------------------- Platform Depended ---------------------------------- // - -#if defined(ENV_OS_LINUX) - -#include -#include -#include -#include - -void CallStackCapture::platformInit() { -} - -void CallStackCapture::platformDeinit() { -} - -void CallStackCapture::platformWriteStackTrace(CallStack* stack) { - auto depth = backtrace((void**) stack->frames, (int) MAX_CALL_DEPTH_CAPTURE - 1); - stack->frames[depth] = 0; -} - -static void getGetSourceFromBinaryAddress(const char* binary, const char* address, char* file, ualni* line) { - static char buff[1024]; - - snprintf(buff, sizeof(buff), "addr2line -e %s -a %s", binary, address); - FILE* pipe = popen(buff, "r"); - if (pipe) { - fgets(buff, sizeof(buff), pipe); - fgets(buff, sizeof(buff), pipe); - pclose(pipe); - char* linePtr = strchr(buff, ':'); - - printf("%s\n", buff); - - if (linePtr != nullptr && buff[0] != '?' && buff[1] != '?' && buff[2] != ':') { - *linePtr = '\0'; - auto sourceLen = std::strlen(buff); - std::strcpy(file, buff + ((sourceLen > CallStackCapture::MAX_DEBUG_INFO_LEN) ? (sourceLen - CallStackCapture::MAX_DEBUG_INFO_LEN) : 0)); - *line = strtoul(linePtr + 1, nullptr, 10); - return; - } - } - - std::strcpy(file, "unresolved"); - *line = 0; -} - -static void getDemangledName(const char* func, char* out) { - int status; - size_t funcDemangledSize = CallStackCapture::MAX_DEBUG_INFO_LEN; - char* funcDemangled = (char*) malloc(funcDemangledSize); - char* ret = abi::__cxa_demangle(func, funcDemangled, &funcDemangledSize, &status); - if (status == 0) { - funcDemangled = ret; - auto funcLen = std::strlen(funcDemangled); - std::strcpy(out, funcDemangled + ((funcLen > CallStackCapture::MAX_DEBUG_INFO_LEN) ? (funcLen - CallStackCapture::MAX_DEBUG_INFO_LEN) : 0)); - free(ret); - return; - } - auto funcLen = std::strlen(func); - std::strcpy(out, func + ((funcLen > CallStackCapture::MAX_DEBUG_INFO_LEN) ? (funcLen - CallStackCapture::MAX_DEBUG_INFO_LEN) : 0)); - free(funcDemangled); -} - -void CallStackCapture::platformWriteDebugSymbols(FramePointer frame, DebugSymbols* out) { - void* addrList[1] = { (void*) frame }; - auto symbolsArray = backtrace_symbols(addrList, 1); - - // 'bin(fun+addr)' - char* bin = *symbolsArray; - char* func = nullptr; - char* offset = nullptr; - - // 'bin fun+addr' - for (char* p = bin; *p; ++p) { - if (*p == '(') { - *p = 0; - func = p + 1; - } else if (*p == '+') { - offset = p; - } else if (*p == ')' && offset) { - *p = 0; - } - } - - if (func && offset) { - getGetSourceFromBinaryAddress(bin, func, out->file, &out->line); - - if (offset != func) { - *offset = 0; - getDemangledName(func, out->function); - } else { - std::strcpy(out->function, "unresolved"); - } - } else { - std::strcpy(out->file, "unresolved"); - std::strcpy(out->function, "unresolved"); - } - - free(symbolsArray); -} - -void CallStackCapture::printSnapshot(const CallStack* snapshot) { - printf("CallStack: \n"); - if (snapshot) { - for (auto frame : *snapshot) { - auto symbols = getSymbols(frame.getFrame()); - printf(" %s ----- %s:%llu\n", symbols->getFunc(), symbols->getFile(), symbols->getLine()); - } - } - printf("\n"); -} - -void CallStackCapture::logAll() { - for (auto cs : *this) { - printSnapshot(cs.getCallStack()); - } -} - -#else -#include -#include -#include - -#pragma comment(lib, "dbghelp.lib") - -void CallStackCapture::platformInit() { - HANDLE process = GetCurrentProcess(); - SymInitialize(process, NULL, TRUE); -} - -void CallStackCapture::platformDeinit() { - HANDLE process = GetCurrentProcess(); - SymCleanup(process); -} - -void CallStackCapture::platformWriteStackTrace(CallStack* stack) { - DWORD hash; - CONTEXT context; - memset(&context, 0, sizeof(CONTEXT)); - context.ContextFlags = CONTEXT_FULL; - RtlCaptureContext(&context); - - STACKFRAME64 stackFrame; - memset(&stackFrame, 0, sizeof(STACKFRAME64)); -#ifdef _M_IX86 - hash = IMAGE_FILE_MACHINE_I386; - stackFrame.AddrPC.Offset = context.Eip; - stackFrame.AddrPC.Mode = AddrModeFlat; - stackFrame.AddrFrame.Offset = context.Ebp; - stackFrame.AddrFrame.Mode = AddrModeFlat; - stackFrame.AddrStack.Offset = context.Esp; - stackFrame.AddrStack.Mode = AddrModeFlat; -#elif _M_X64 - hash = IMAGE_FILE_MACHINE_AMD64; - stackFrame.AddrPC.Offset = context.Rip; - stackFrame.AddrPC.Mode = AddrModeFlat; - stackFrame.AddrFrame.Offset = context.Rbp; - stackFrame.AddrFrame.Mode = AddrModeFlat; - stackFrame.AddrStack.Offset = context.Rsp; - stackFrame.AddrStack.Mode = AddrModeFlat; -#endif - - for (int frameIndex = 0; frameIndex < MAX_CALL_DEPTH_CAPTURE; ++frameIndex) { - if (!StackWalk64( - hash, - GetCurrentProcess(), - GetCurrentThread(), - &stackFrame, - &context, - NULL, - SymFunctionTableAccess64, - SymGetModuleBase64, - NULL - )) { - - stack->frames[frameIndex] = 0; - break; - } - stack->frames[frameIndex] = (alni) (void*) stackFrame.AddrPC.Offset; - } - stack->frames[MAX_CALL_DEPTH_CAPTURE - 1] = 0; -} - -void CallStackCapture::platformWriteDebugSymbols(FramePointer frame, DebugSymbols* out) { - HANDLE process = GetCurrentProcess(); - - IMAGEHLP_LINE64 lineInfo; - DWORD displacement; - lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64); - if (SymGetLineFromAddr64(process, (DWORD64) frame, &displacement, &lineInfo)) { - strcpy(out->file, lineInfo.FileName); - out->line = lineInfo.LineNumber; - } else { - strcpy(out->file, "unresolved"); - out->line = 0; - } - - DWORD64 displacementSym = 0; - char symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + MAX_PATH] = { 0 }; - IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*) symbolBuffer; - symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); - symbol->MaxNameLength = MAX_PATH; - - if (SymGetSymFromAddr64(process, (DWORD64) frame, &displacementSym, symbol)) { - strcpy(out->function, symbol->Name); - } else { - strcpy(out->function, "unresolved"); - } -} - -void CallStackCapture::printSnapshot(const CallStack* snapshot) { - printf("CallStack: \n"); - if (snapshot) { - for (int i = 0; i < snapshot->getDepth(); ++i) { - DebugSymbols symbols; - platformWriteDebugSymbols(snapshot->frames[i], &symbols); - printf(" %s ----- %s:%lu\n", symbols.function, symbols.file, symbols.line); - } - } - printf("\n"); -} - -void CallStackCapture::logAll() { - for (auto cs : *this) { - printSnapshot(cs.getCallStack()); - } -} -#endif \ No newline at end of file diff --git a/Callstack/public/Callstack.hpp b/Callstack/public/Callstack.hpp deleted file mode 100644 index aac0e3c..0000000 --- a/Callstack/public/Callstack.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include "Environment.hpp" -#include "Map.hpp" - -namespace tp { - - class CallStackCapture { - public: - typedef tp::alni FramePointer; - - bool initialized = false; - - enum { - MAX_CALL_DEPTH_CAPTURE = 16, - MAX_CALL_CAPTURES_MEM_SIZE_MB = 32, - MAX_DEBUG_INFO_LEN = 64, - }; - - class CallStack { - friend CallStackCapture; - FramePointer frames[MAX_CALL_DEPTH_CAPTURE]; - - public: - [[nodiscard]] ualni getDepth() const; - - class Iterator { - const FramePointer* mFrame; - - public: - explicit Iterator(const FramePointer* frame) : mFrame(frame){}; - FramePointer getFrame() { return *mFrame; } - bool operator==(const Iterator& in) const { return in.mFrame == mFrame; } - void operator++() { mFrame++; } - const Iterator& operator*() const { return *this; } - }; - - [[nodiscard]] Iterator begin() const { return Iterator(frames); } - [[nodiscard]] Iterator end() const { return Iterator(frames + getDepth()); } - }; - - enum { STACKS_LENGTH = (MAX_CALL_CAPTURES_MEM_SIZE_MB * 1024 * 1024) / sizeof(CallStack) }; - - class DebugSymbols { - friend CallStackCapture; - char function[MAX_DEBUG_INFO_LEN + 1] = { 0 }; - char file[MAX_DEBUG_INFO_LEN + 1] = { 0 }; - ualni line = 0; - - public: - [[nodiscard]] const char* getFunc() const { return function; } - [[nodiscard]] const char* getFile() const { return file; } - [[nodiscard]] ualni getLine() const { return line; } - }; - - public: - CallStackCapture(); - ~CallStackCapture(); - - [[nodiscard]] const CallStack* getSnapshot(); - const DebugSymbols* getSymbols(FramePointer fp); - - void printSnapshot(const CallStack* snapshot); - void logAll(); - - public: - class Iterator { - const CallStack* mSnapshot; - - public: - explicit Iterator(const CallStack* start) : mSnapshot(start) {}; - const CallStack* getCallStack() { return mSnapshot; } - bool operator==(const Iterator& in) const { return in.mSnapshot == mSnapshot; } - void operator++() { mSnapshot++; } - const Iterator& operator*() const { return *this; } - }; - - [[nodiscard]] Iterator begin() const { return Iterator(mBuff); } - [[nodiscard]] Iterator end() const { return Iterator(mBuff + mBuffLoad); } - - private: - struct CallStackKey { - CallStack* cs; - bool operator==(const CallStackKey& in) const; - }; - - static void platformWriteStackTrace(CallStack* stack); - static void platformWriteDebugSymbols(FramePointer frame, DebugSymbols* out); - [[nodiscard]] static ualni hashCallStack(CallStackKey key); - void platformInit(); - void platformDeinit(); - - void clear(); - - private: - CallStack mErrorSnapshot; - - ualni mBuffLen; - ualni mBuffLoad; - CallStack* mBuff; - - Map mSnapshots; - Map mSymbols; - }; -} diff --git a/Callstack/tests/Test.cpp b/Callstack/tests/Test.cpp deleted file mode 100644 index e5ed3b7..0000000 --- a/Callstack/tests/Test.cpp +++ /dev/null @@ -1,44 +0,0 @@ - -#include "UnitTest++/UnitTest++.h" - -#include "Callstack.hpp" - -#include - -using namespace tp; - -void common(CallStackCapture& cs) { auto tmp = cs.getSnapshot(); } - -void first(CallStackCapture& cs) { - common(cs); - common(cs); - common(cs); -} - -void second(CallStackCapture& cs) { - common(cs); - common(cs); - common(cs); - common(cs); -} - -void third(CallStackCapture& cs) { - common(cs); - common(cs); -} - -void root(CallStackCapture& cs) { - first(cs); - second(cs); - third(cs); -} - -SUITE(Utils) { - TEST(CallStackCapture) { - CallStackCapture callstack; - root(callstack); - callstack.logAll(); - } -} - -int main() { return UnitTest::RunAllTests(); } \ No newline at end of file