From c27187ae4b83034796a55d8d223589c2c5adcf58 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 28 May 2014 10:02:43 +0200 Subject: [PATCH] Added MemoryPool class Former-commit-id: cc704583a686dd631bee54ed48cee913aeb2e369 --- include/Nazara/Core/MemoryPool.hpp | 36 +++++++++++++ include/Nazara/Core/MemoryPool.inl | 87 ++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 include/Nazara/Core/MemoryPool.hpp create mode 100644 include/Nazara/Core/MemoryPool.inl diff --git a/include/Nazara/Core/MemoryPool.hpp b/include/Nazara/Core/MemoryPool.hpp new file mode 100644 index 000000000..0e9fb32e9 --- /dev/null +++ b/include/Nazara/Core/MemoryPool.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2014 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_MEMORYPOOL_HPP +#define NAZARA_MEMORYPOOL_HPP + +#include +#include + +template +class NzMemoryPool +{ + public: + NzMemoryPool(); + ~NzMemoryPool() = default; + + template T* Allocate(); + void* Allocate(unsigned int size); + void Free(void* ptr); + + private: + NzMemoryPool(NzMemoryPool* pool); + + std::unique_ptr m_freeList; + std::unique_ptr m_pool; + std::unique_ptr m_next; + NzMemoryPool* m_previous; + unsigned int m_freeCount; +}; + +#include + +#endif // NAZARA_MEMORYPOOL_HPP diff --git a/include/Nazara/Core/MemoryPool.inl b/include/Nazara/Core/MemoryPool.inl new file mode 100644 index 000000000..21c07a828 --- /dev/null +++ b/include/Nazara/Core/MemoryPool.inl @@ -0,0 +1,87 @@ +// Copyright (C) 2014 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +template +NzMemoryPool::NzMemoryPool() : +m_previous(nullptr), +m_freeCount(count) +{ + m_pool.reset(new nzUInt8[typeSize * 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)]; +} + +template +NzMemoryPool::NzMemoryPool(NzMemoryPool* pool) : +NzMemoryPool() +{ + m_previous = pool; +} + +template +template +T* NzMemoryPool::Allocate() +{ + static_assert(sizeof(T) <= typeSize, "This type is too large for this memory pool"); + + return static_cast(Allocate(sizeof(T))); +} + +template +void* NzMemoryPool::Allocate(unsigned int size) +{ + if (size > typeSize) + { + 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); + } + + throw std::bad_alloc(); + return nullptr; +} + +template +void NzMemoryPool::Free(void* ptr) +{ + if (ptr) + { + // Le pointer nous appartient-il ? + if (ptr >= m_pool.get() && ptr < m_pool.get() + typeSize*count) + { + m_freeList[m_freeCount++] = ptr; + + // Si nous somme vide et l'extension d'un autre pool, on se suicide + if (m_freeCount == count && m_previous && !m_next) + { + m_previous->m_next.release(); + delete this; // Suicide + } + } + else + { + if (m_next) + m_next->Free(ptr); + else + throw std::runtime_error("Pointer does not belong to memory pool"); + } + } +} + +#include