diff --git a/include/Nazara/Core/MemoryPool.hpp b/include/Nazara/Core/MemoryPool.hpp index c53df3786..2fecdeb61 100644 --- a/include/Nazara/Core/MemoryPool.hpp +++ b/include/Nazara/Core/MemoryPool.hpp @@ -11,11 +11,12 @@ #include #include -template class NzMemoryPool { public: - NzMemoryPool(unsigned int size = 1024); + NzMemoryPool(unsigned int blockSize, unsigned int size = 1024, bool canGrow = true); + NzMemoryPool(const NzMemoryPool&) = delete; + NzMemoryPool(NzMemoryPool&& pool) noexcept; ~NzMemoryPool() = default; template T* Allocate(); @@ -23,9 +24,13 @@ class NzMemoryPool void Free(void* ptr); + unsigned int GetBlockSize() const; unsigned int GetFreeBlocks() const; unsigned int GetSize() const; + NzMemoryPool& operator=(const NzMemoryPool&) = delete; + NzMemoryPool& operator=(NzMemoryPool&& pool) noexcept; + private: NzMemoryPool(NzMemoryPool* pool); @@ -34,6 +39,8 @@ class NzMemoryPool std::unique_ptr m_next; std::atomic_uint m_freeCount; NzMemoryPool* m_previous; + bool m_canGrow; + unsigned int m_blockSize; unsigned int m_size; }; diff --git a/include/Nazara/Core/MemoryPool.inl b/include/Nazara/Core/MemoryPool.inl index 0ad5c3398..49463ad7f 100644 --- a/include/Nazara/Core/MemoryPool.inl +++ b/include/Nazara/Core/MemoryPool.inl @@ -3,46 +3,48 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include -template -NzMemoryPool::NzMemoryPool(unsigned int count) : -m_freeCount(count), +inline NzMemoryPool::NzMemoryPool(unsigned int blockSize, unsigned int size, bool canGrow) : +m_freeCount(size), m_previous(nullptr), -m_size(count) +m_canGrow(canGrow), +m_blockSize(blockSize), +m_size(size) { - m_pool.reset(new nzUInt8[blockSize * count]); - m_freeList.reset(new void*[count]); + m_pool.reset(new nzUInt8[blockSize * size]); + m_freeList.reset(new void*[size]); // Remplissage de la free list - for (unsigned int i = 0; i < count; ++i) - m_freeList[i] = &m_pool[blockSize * (count-i-1)]; + for (unsigned int i = 0; i < size; ++i) + m_freeList[i] = &m_pool[m_blockSize * (size-i-1)]; } -template -NzMemoryPool::NzMemoryPool(NzMemoryPool* pool) : -NzMemoryPool(pool->m_size) +inline NzMemoryPool::NzMemoryPool(NzMemoryPool&& pool) noexcept +{ + operator=(std::move(pool)); +} + +inline NzMemoryPool::NzMemoryPool(NzMemoryPool* pool) : +NzMemoryPool(pool->m_blockSize, pool->m_size, pool->m_canGrow) { m_previous = pool; } -template template -T* NzMemoryPool::Allocate() +inline T* NzMemoryPool::Allocate() { - 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) +inline void* NzMemoryPool::Allocate(unsigned int size) { - if (size <= blockSize) + if (size <= m_blockSize) { if (m_freeCount > 0) return m_freeList[--m_freeCount]; - else if (canGrow) + else if (m_canGrow) { if (!m_next) m_next.reset(new NzMemoryPool(this)); @@ -54,22 +56,18 @@ void* NzMemoryPool::Allocate(unsigned int size) return NzOperatorNew(size); } -template -void NzMemoryPool::Free(void* ptr) +inline void NzMemoryPool::Free(void* ptr) { if (ptr) { - // Le pointer nous appartient-il ? + // Le pointeur nous appartient-il ? nzUInt8* freePtr = static_cast(ptr); nzUInt8* poolPtr = m_pool.get(); - if (freePtr >= poolPtr && freePtr < poolPtr + blockSize*m_size) + if (freePtr >= poolPtr && freePtr < poolPtr + m_blockSize*m_size) { #if NAZARA_CORE_SAFE - if ((freePtr - poolPtr) % blockSize != 0) - { - throw std::runtime_error("Pointer does not belong to memory pool"); - return; - } + if ((freePtr - poolPtr) % m_blockSize != 0) + throw std::runtime_error("Invalid pointer (does not point to an element of the pool)"); #endif m_freeList[m_freeCount++] = ptr; @@ -91,16 +89,40 @@ void NzMemoryPool::Free(void* ptr) } } -template -unsigned int NzMemoryPool::GetFreeBlocks() const +inline unsigned int NzMemoryPool::GetBlockSize() const +{ + return m_blockSize; +} + +inline unsigned int NzMemoryPool::GetFreeBlocks() const { return m_freeCount; } -template -unsigned int NzMemoryPool::GetSize() const +inline unsigned int NzMemoryPool::GetSize() const { return m_size; } +inline NzMemoryPool& NzMemoryPool::operator=(NzMemoryPool&& pool) noexcept +{ + m_blockSize = m_blockSize; + m_canGrow = m_canGrow; + m_freeCount = m_freeCount.load(); + m_freeList = std::move(m_freeList); + m_pool = std::move(m_pool); + m_previous = m_previous; + m_next = std::move(m_next); + m_size = m_size; + + // Si nous avons été créés par un autre pool, nous devons le faire pointer vers nous de nouveau + if (m_previous) + { + m_previous->m_next.release(); + m_previous->m_next.reset(this); + } + + return *this; +} + #include