diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 3564434..c285479 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -2,6 +2,7 @@ file(GLOB COMMON_SOURCES "*.cpp" "datamgr/*.cpp" "datastore/*.cpp" + "memory/*.cpp" "mempool/*.cpp" "objectalloc/*.cpp" "processor/*.cpp" diff --git a/common/DataAllocator.hpp b/common/DataAllocator.hpp new file mode 100644 index 0000000..d8c1cca --- /dev/null +++ b/common/DataAllocator.hpp @@ -0,0 +1,6 @@ +#ifndef COMMON_DATA_ALLOCATOR_HPP +#define COMMON_DATA_ALLOCATOR_HPP + +#include "common/memory/CDataAllocator.hpp" + +#endif diff --git a/common/memory/CDataAllocator.cpp b/common/memory/CDataAllocator.cpp new file mode 100644 index 0000000..280bdf8 --- /dev/null +++ b/common/memory/CDataAllocator.cpp @@ -0,0 +1,94 @@ +#include "common/memory/CDataAllocator.hpp" + +#include + +#include +#include + +CDataAllocator::CDataAllocator(uint32_t bytesPerData, uint32_t dataPerBlock) { + this->m_bytesPerData = std::max(bytesPerData, 4u); + this->m_dataPerBlock = std::max(dataPerBlock, 1u); +} + +CDataAllocator::~CDataAllocator() { +} + +void CDataAllocator::Clear(const char* fileName, int32_t lineNumber) { + if (this->m_dataUsed) { + if (!fileName) { + fileName == __FILE__; + lineNumber = __LINE__; + } + + SErrDisplayErrorFmt( + 0x8510007E, + fileName, + lineNumber, + 1, + 1, + "CDataAllocator@0x%08x: leaked %u: %s(%d) [%u][%u]", + this, + this->m_dataUsed, + fileName, + lineNumber, + this->m_dataPerBlock, + this->m_bytesPerData); + } + + while (this->m_blockList) { + auto block = this->m_blockList; + this->m_blockList = block->m_next; + SMemFree(block); + } + + this->m_dataUsed = 0; + this->m_dataList = 0; +} + +CDataAllocator::Data* CDataAllocator::GetData(int32_t zero, const char* fileName, int32_t lineNumber) { + if (this->m_dataPerBlock == 1) { + fileName = nullptr; + lineNumber = 0; + } + + if (!this->m_dataList) { + if (!fileName) { + fileName = __FILE__; + lineNumber = __LINE__; + } + + auto memory = static_cast(SMemAlloc( + this->m_dataPerBlock * this->m_bytesPerData + sizeof(Data), + fileName, + lineNumber, + 0)); + Block* block = reinterpret_cast(memory); + Data* data = reinterpret_cast(memory + sizeof(Block*)); + + this->m_dataList = data; + for (uint32_t i = 0; i < this->m_dataPerBlock - 1; ++i) { + auto next = reinterpret_cast(data) + this->m_bytesPerData; + data->m_next = reinterpret_cast(next); + data = data->m_next; + } + data->m_next = 0; + block->m_next = this->m_blockList; + this->m_blockList = block; + } + + auto data = this->m_dataList; + this->m_dataList = data->m_next; + if (zero) { + memset(data, 0, this->m_bytesPerData); + } + this->m_dataUsed++; + return data; +} + +void CDataAllocator::PutData(void* data, const char* fileName, int32_t lineNumber) { + STORM_ASSERT(this->m_dataUsed > 0); + auto d = reinterpret_cast(data); + d->m_next = this->m_dataList; + this->m_dataUsed--; + this->m_dataList = d; +} diff --git a/common/memory/CDataAllocator.hpp b/common/memory/CDataAllocator.hpp new file mode 100644 index 0000000..7ae1641 --- /dev/null +++ b/common/memory/CDataAllocator.hpp @@ -0,0 +1,32 @@ +#ifndef COMMON_MEMORY_C_DATA_ALLOCATOR_HPP +#define COMMON_MEMORY_C_DATA_ALLOCATOR_HPP + +#include + +class CDataAllocator { + public: + // Sub-types + struct Block { + Block* m_next; + }; + + struct Data { + Data* m_next; + }; + + // Member functions + CDataAllocator(uint32_t bytesPerData, uint32_t dataPerBlock); + ~CDataAllocator(); + void Clear(const char* fileName, int32_t lineNumber); + Data* GetData(int32_t zero, const char* fileName, int32_t lineNumber); + void PutData(void* data, const char* fileName, int32_t lineNumber); + + // Member variables + uint32_t m_bytesPerData = sizeof(Data); + uint32_t m_dataPerBlock = 1; + uint32_t m_dataUsed = 0; + Block* m_blockList = nullptr; + Data* m_dataList = nullptr; +}; + +#endif