From f55b151c8ed2cfbd13ac1838ef218c2349a4cd13 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 15 Jun 2014 01:17:57 +0200 Subject: [PATCH] Improved MemoryPool class It's size is now dynamic (defaulted to 1024) Added MemoryPool::GetFreeBlocks() Added MemoryPool::GetSize() Tried to make it thread-safe It supports dynamics allocations (in case where it can't allocate memory from the pool for some reasons) Former-commit-id: 1cc6cb2bc118556363a5c8ba1d18b3b1ce734862 --- include/Nazara/Core/MemoryPool.hpp | 12 +++-- include/Nazara/Core/MemoryPool.inl | 77 +++++++++++++++++------------- 2 files changed, 52 insertions(+), 37 deletions(-) diff --git a/include/Nazara/Core/MemoryPool.hpp b/include/Nazara/Core/MemoryPool.hpp index 0e9fb32e9..64efc4ccd 100644 --- a/include/Nazara/Core/MemoryPool.hpp +++ b/include/Nazara/Core/MemoryPool.hpp @@ -8,27 +8,33 @@ #define NAZARA_MEMORYPOOL_HPP #include +#include #include -template +template class NzMemoryPool { public: - NzMemoryPool(); + NzMemoryPool(unsigned int size = 1024); ~NzMemoryPool() = default; template T* Allocate(); void* Allocate(unsigned int size); + void Free(void* ptr); + unsigned int GetFreeBlocks() const; + unsigned int GetSize() const; + private: NzMemoryPool(NzMemoryPool* pool); std::unique_ptr m_freeList; std::unique_ptr m_pool; std::unique_ptr m_next; + std::atomic_uint m_freeCount; NzMemoryPool* m_previous; - unsigned int m_freeCount; + unsigned int m_size; }; #include diff --git a/include/Nazara/Core/MemoryPool.inl b/include/Nazara/Core/MemoryPool.inl index 592fb38fc..1d44075ad 100644 --- a/include/Nazara/Core/MemoryPool.inl +++ b/include/Nazara/Core/MemoryPool.inl @@ -5,70 +5,67 @@ #include #include -template -NzMemoryPool::NzMemoryPool() : +template +NzMemoryPool::NzMemoryPool(unsigned int count) : +m_freeCount(count), m_previous(nullptr), -m_freeCount(count) +m_size(count) { - m_pool.reset(new nzUInt8[typeSize * count]); + m_pool.reset(new nzUInt8[blockSize * count]); m_freeList.reset(new void*[count]); // Remplissage de la free list for (unsigned int i = 0; i < count; ++i) - m_freeList[i] = &m_pool[typeSize * (count-i-1)]; + m_freeList[i] = &m_pool[blockSize * (count-i-1)]; } -template -NzMemoryPool::NzMemoryPool(NzMemoryPool* pool) : -NzMemoryPool() +template +NzMemoryPool::NzMemoryPool(NzMemoryPool* pool) : +NzMemoryPool(pool->m_size) { m_previous = pool; } -template +template template -T* NzMemoryPool::Allocate() +T* NzMemoryPool::Allocate() { - static_assert(sizeof(T) <= typeSize, "This type is too large for this memory pool"); + static_assert(sizeof(T) <= blockSize, "This type is too large for this memory pool"); return static_cast(Allocate(sizeof(T))); } -template -void* NzMemoryPool::Allocate(unsigned int size) +template +void* NzMemoryPool::Allocate(unsigned int size) { - if (size > typeSize) + if (size <= blockSize) { - throw std::bad_alloc(); - return nullptr; + if (m_freeCount > 0) + return m_freeList[--m_freeCount]; + else if (canGrow) + { + if (!m_next) + m_next.reset(new NzMemoryPool(this)); + + return m_next->Allocate(size); + } } - if (m_freeCount > 0) - return m_freeList[--m_freeCount]; - else if (canGrow) - { - if (!m_next) - m_next.reset(new NzMemoryPool(this)); - - return m_next->Allocate(size); - } - - throw std::bad_alloc(); - return nullptr; + return operator new(size); } -template -void NzMemoryPool::Free(void* ptr) +template +void NzMemoryPool::Free(void* ptr) { if (ptr) { // Le pointer nous appartient-il ? nzUInt8* freePtr = static_cast(ptr); nzUInt8* poolPtr = m_pool.get(); - if (freePtr >= poolPtr && freePtr < poolPtr + typeSize*count) + if (freePtr >= poolPtr && freePtr < poolPtr + blockSize*m_size) { #if NAZARA_CORE_SAFE - if ((freePtr - poolPtr) % typeSize != 0) + if ((freePtr - poolPtr) % blockSize != 0) { throw std::runtime_error("Pointer does not belong to memory pool"); return; @@ -78,7 +75,7 @@ void NzMemoryPool::Free(void* ptr) m_freeList[m_freeCount++] = ptr; // Si nous sommes vide et l'extension d'un autre pool, on se suicide - if (m_freeCount == count && m_previous && !m_next) + if (m_freeCount == m_size && m_previous && !m_next) { m_previous->m_next.release(); delete this; // Suicide @@ -89,9 +86,21 @@ void NzMemoryPool::Free(void* ptr) if (m_next) m_next->Free(ptr); else - throw std::runtime_error("Pointer does not belong to memory pool"); + operator delete(ptr); } } } +template +unsigned int NzMemoryPool::GetFreeBlocks() const +{ + return m_freeCount; +} + +template +unsigned int NzMemoryPool::GetSize() const +{ + return m_size; +} + #include