Apply formating to all files. CLeanup

This commit is contained in:
IlyaShurupov 2023-10-22 17:07:28 +03:00
parent 43e374f269
commit 744c01c5d0
928 changed files with 14515 additions and 21480 deletions

View file

@ -3,25 +3,22 @@
#include <cstdlib>
static void deinit(const tp::ModuleManifest* self) {
tp::HeapAllocGlobal::checkLeaks();
}
static void deinit(const tp::ModuleManifest* self) { tp::HeapAllocGlobal::checkLeaks(); }
static tp::ModuleManifest* sModuleDependencies[] = { &tp::gModuleUtils, nullptr };
tp::ModuleManifest tp::gModuleAllocators = ModuleManifest("Allocators", nullptr, deinit, sModuleDependencies);
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 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 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); }
void operator delete(void* aPtr, tp::HeapAllocGlobal& aAlloc) { tp::HeapAllocGlobal::deallocate(aPtr); }
void operator delete[](void* aPtr, tp::HeapAllocGlobal& aAlloc) { tp::HeapAllocGlobal::deallocate(aPtr); }

View file

@ -1,70 +1,69 @@
#include "HeapAllocator.hpp"
#include "HeapAllocatorGlobal.hpp"
#include "PrivateConfig.hpp"
using namespace tp;
#if not defined(MEM_DEBUG)
// ----------------------- Release Implementation ---------------------------- //
void* HeapAlloc::allocate(ualni aBlockSize) { return malloc(aBlockSize); }
void HeapAlloc::deallocate(void* aPtr) { 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) {
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_BREAK("Destruction of not freed Allocator")
#ifdef MEM_STACK_TRACE
// TODO : log leaks and free them up
#endif
}
}
#endif
#include "HeapAllocator.hpp"
#include "HeapAllocatorGlobal.hpp"
#include "PrivateConfig.hpp"
using namespace tp;
#if not defined(MEM_DEBUG)
// ----------------------- Release Implementation ---------------------------- //
void* HeapAlloc::allocate(ualni aBlockSize) { return malloc(aBlockSize); }
void HeapAlloc::deallocate(void* aPtr) { 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) {
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_BREAK("Destruction of not freed Allocator")
#ifdef MEM_STACK_TRACE
// TODO : log leaks and free them up
#endif
}
}
#endif

View file

@ -1,198 +1,196 @@
#include "HeapAllocatorGlobal.hpp"
#include "PrivateConfig.hpp"
#include "Utils.hpp"
#include "Debugging.hpp"
#include <cstdio>
#include <cstdlib>
using namespace tp;
#if not defined(MEM_DEBUG)
// ----------------------- Release Implementation ---------------------------- //
void* HeapAllocGlobal::allocate(ualni aBlockSize) { return malloc(aBlockSize); }
void HeapAllocGlobal::deallocate(void* aPtr) { free(aPtr); }
HeapAllocGlobal::~HeapAllocGlobal() = default;
#else
tp::MemHead* tp::HeapAllocGlobal::mEntry = nullptr;
tp::ualni tp::HeapAllocGlobal::mNumAllocations = 0;
tp::Mutex tp::HeapAllocGlobal::mMutex;
bool tp::HeapAllocGlobal::mIgnore;
// ----------------------- 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;
#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
head->mCallStack = gCSCapture->getSnapshot();
#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;
}
mMutex.unlock();
if (!head->mIgnored) {
// 3) Check the wrap
if (memCompareVal(wrap_top, WRAP_SIZE, WRAP_VAL)) {
CallStackCapture::printSnapshot(head->mCallStack);
ASSERT(!"Allocated Block Wrap Corrupted!")
}
if (memCompareVal(wrap_bottom, WRAP_SIZE, WRAP_VAL)) {
CallStackCapture::printSnapshot(head->mCallStack);
ASSERT(!"Allocated Block Wrap Corrupted!")
}
// 4) clear data
#ifdef MEM_CLEAR_ON_ALLOC
memSetVal(data, head->mBlockSize, CLEAR_DEALLOC_VAL);
#endif
}
// 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) CallStackCapture::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();
}
HeapAllocGlobal::~HeapAllocGlobal() = default;
#endif
#include "HeapAllocatorGlobal.hpp"
#include "PrivateConfig.hpp"
#include "Debugging.hpp"
#include "Utils.hpp"
#include <cstdio>
#include <cstdlib>
using namespace tp;
#if not defined(MEM_DEBUG)
// ----------------------- Release Implementation ---------------------------- //
void* HeapAllocGlobal::allocate(ualni aBlockSize) { return malloc(aBlockSize); }
void HeapAllocGlobal::deallocate(void* aPtr) { free(aPtr); }
HeapAllocGlobal::~HeapAllocGlobal() = default;
#else
tp::MemHead* tp::HeapAllocGlobal::mEntry = nullptr;
tp::ualni tp::HeapAllocGlobal::mNumAllocations = 0;
tp::Mutex tp::HeapAllocGlobal::mMutex;
bool tp::HeapAllocGlobal::mIgnore;
// ----------------------- 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;
#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
head->mCallStack = gCSCapture->getSnapshot();
#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;
}
mMutex.unlock();
if (!head->mIgnored) {
// 3) Check the wrap
if (memCompareVal(wrap_top, WRAP_SIZE, WRAP_VAL)) {
CallStackCapture::printSnapshot(head->mCallStack);
ASSERT(!"Allocated Block Wrap Corrupted!")
}
if (memCompareVal(wrap_bottom, WRAP_SIZE, WRAP_VAL)) {
CallStackCapture::printSnapshot(head->mCallStack);
ASSERT(!"Allocated Block Wrap Corrupted!")
}
// 4) clear data
#ifdef MEM_CLEAR_ON_ALLOC
memSetVal(data, head->mBlockSize, CLEAR_DEALLOC_VAL);
#endif
}
// 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) CallStackCapture::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();
}
HeapAllocGlobal::~HeapAllocGlobal() = default;
#endif

View file

@ -2,9 +2,9 @@
#include "Utils.hpp"
#include "HeapAllocatorGlobal.hpp"
#include "HeapAllocator.hpp"
#include "ChunkAllocator.hpp"
#include "HeapAllocator.hpp"
#include "HeapAllocatorGlobal.hpp"
#include "PoolAllocator.hpp"
namespace tp {
@ -13,15 +13,15 @@ namespace tp {
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 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 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);
void operator delete(void* aPtr, tp::HeapAllocGlobal& aAlloc);
void operator delete[](void* aPtr, tp::HeapAllocGlobal& aAlloc);

View file

@ -14,8 +14,8 @@
* 2) updating list entry to that block.
*/
#include "HeapAllocatorGlobal.hpp"
#include "Environment.hpp"
#include "HeapAllocatorGlobal.hpp"
#include "PrivateConfig.hpp"
namespace tp {
@ -23,7 +23,7 @@ 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<typename tType, ualni tNumBlocks>
template <typename tType, ualni tNumBlocks>
class ChunkAlloc {
enum : ualni {
@ -76,24 +76,24 @@ namespace tp {
// 2) Find free block and update next free block
auto data = mNextBlock;
mNextBlock = (ualni*)(*data);
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();
#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);
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
// 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
data += WRAP_SIZE_ALN;
#endif
return data;
}
@ -101,26 +101,26 @@ namespace tp {
void deallocate(void* aPtr) {
DEBUG_ASSERT(aPtr >= mBuff && aPtr < mBuff + tNumBlocks * blockSize())
auto block = (ualni*)aPtr;
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;
#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!")
// 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
// 4) Clear data
#ifdef MEM_CLEAR_ON_ALLOC
memSetVal(block, blockSize() * ALIGNED_SIZE, CLEAR_DEALLOC_VAL);
#endif
#endif
#endif
(*block) = (ualni)mNextBlock;
(*block) = (ualni) mNextBlock;
mNextBlock = block;
mNumFreeBlocks++;
}

View file

@ -21,14 +21,14 @@ namespace tp {
// Pool Allocator
// Overcomes chunk allocator fixed number of max allocations
template<typename tType, ualni tNumBlocks>
template <typename tType, ualni tNumBlocks>
class PoolAlloc {
typedef ChunkAlloc<tType, tNumBlocks> Chunk;
struct Chunks {
void add(Chunk* aChunk){
void add(Chunk* aChunk) {
if (!mBuff) {
mLen = 16;
@ -57,7 +57,7 @@ namespace tp {
}
}
void remove(Chunk** del_address){
void remove(Chunk** del_address) {
if (mUsedLen == 1) {
mLen = 0;
mUsedLen = 0;
@ -74,18 +74,16 @@ namespace tp {
mUsedLen--;
// check for buff low usage
if ((halnf)mUsedLen / (halnf)mLen < 0.25f) {
if ((halnf) mUsedLen / (halnf) mLen < 0.25f) {
auto prevBuff = mBuff;
mBuff = (Chunk**)HeapAllocGlobal::allocate(sizeof(Chunk*) * mLen / 2);
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** find(void* aPtr) { return findUtil(mBuff, mBuff + mUsedLen, aPtr) - 1; }
[[nodiscard]] Chunk* findNotFull() const {
for (ualni idx = 0; idx < mUsedLen; idx++) {
@ -137,9 +135,9 @@ namespace tp {
auto chunk = mChunks.find(aPtr);
(*chunk)->deallocate(aPtr);
if ((*chunk)->isEmpty()) {
if (mFreeChunk == *chunk) mFreeChunk = nullptr;
HeapAllocGlobal::deallocate(*chunk);
mChunks.remove(chunk);
if (mFreeChunk == *chunk) mFreeChunk = nullptr;
HeapAllocGlobal::deallocate(*chunk);
mChunks.remove(chunk);
}
}
@ -153,7 +151,7 @@ namespace tp {
if (i > j) {
ASSERT(mChunks.mBuff[i] > mChunks.mBuff[j])
} else if (i < j) {
ASSERT(mChunks.mBuff[i] < mChunks.mBuff[j])
ASSERT(mChunks.mBuff[i] < mChunks.mBuff[j])
}
}
}

View file

@ -1,20 +1,20 @@
#include "Allocators.hpp"
#include "Tests.hpp"
using namespace tp;
int main() {
tp::ModuleManifest* deps[] = { &tp::gModuleAllocators, &tp::gModuleUtils, nullptr };
tp::ModuleManifest testModule("AllocatorsTest", nullptr, nullptr, deps);
if (!testModule.initialize()) {
return 1;
}
testAll();
testModule.deinitialize();
}
#include "Allocators.hpp"
#include "Tests.hpp"
using namespace tp;
int main() {
tp::ModuleManifest* deps[] = { &tp::gModuleAllocators, &tp::gModuleUtils, nullptr };
tp::ModuleManifest testModule("AllocatorsTest", nullptr, nullptr, deps);
if (!testModule.initialize()) {
return 1;
}
testAll();
testModule.deinitialize();
}

View file

@ -1,6 +1,6 @@
#pragma once
#include "Utils.hpp"
#include "Testing.hpp"
#include "Utils.hpp"
void testAll();

View file

@ -1,248 +1,245 @@
#include "Utils.hpp"
#include "Testing.hpp"
#include "HeapAllocatorGlobal.hpp"
#include "HeapAllocator.hpp"
#include "ChunkAllocator.hpp"
#include "PoolAllocator.hpp"
#include <cmath>
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 <alni tSize, class tAllocator>
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<alni> 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]);
TEST(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<alni> 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;
TEST(!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 = 1000;
template<typename Alloc>
void testAlloc() {
try {
TestBenches<size, Alloc> heapTests{};
heapTests.runTests();
} catch (...) {
TEST(false);
}
}
TEST_DEF_STATIC(GlobalHeap) {
testAlloc<HeapAllocGlobal>();
}
TEST_DEF_STATIC(Heap) {
testAlloc<HeapAlloc>();
}
TEST_DEF_STATIC(Chunk) {
testAlloc<ChunkAlloc<TestStruct, size>>();
testAlloc<ChunkAlloc<TestStruct, size * 2>>();
}
TEST_DEF_STATIC(Pool) {
testAlloc<PoolAlloc<TestStruct, 1>>();
testAlloc<PoolAlloc<TestStruct, size / 100>>();
testAlloc<PoolAlloc<TestStruct, size>>();
}
TEST_DEF_STATIC(Simple) {
auto a = new TestStruct(-1);
delete a;
}
TEST_DEF(All) {
testSimple();
testGlobalHeap();
testHeap();
testChunk();
testPool();
// TEST(HeapAllocGlobal::checkLeaks());
// TEST(false);
#include "Testing.hpp"
#include "Utils.hpp"
#include "ChunkAllocator.hpp"
#include "HeapAllocator.hpp"
#include "HeapAllocatorGlobal.hpp"
#include "PoolAllocator.hpp"
#include <cmath>
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 <alni tSize, class tAllocator>
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<alni> 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]);
TEST(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<alni> 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;
TEST(!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 = 1000;
template <typename Alloc>
void testAlloc() {
try {
TestBenches<size, Alloc> heapTests{};
heapTests.runTests();
} catch (...) {
TEST(false);
}
}
TEST_DEF_STATIC(GlobalHeap) { testAlloc<HeapAllocGlobal>(); }
TEST_DEF_STATIC(Heap) { testAlloc<HeapAlloc>(); }
TEST_DEF_STATIC(Chunk) {
testAlloc<ChunkAlloc<TestStruct, size>>();
testAlloc<ChunkAlloc<TestStruct, size * 2>>();
}
TEST_DEF_STATIC(Pool) {
testAlloc<PoolAlloc<TestStruct, 1>>();
testAlloc<PoolAlloc<TestStruct, size / 100>>();
testAlloc<PoolAlloc<TestStruct, size>>();
}
TEST_DEF_STATIC(Simple) {
auto a = new TestStruct(-1);
delete a;
}
TEST_DEF(All) {
testSimple();
testGlobalHeap();
testHeap();
testChunk();
testPool();
// TEST(HeapAllocGlobal::checkLeaks());
// TEST(false);
}