diff --git a/src/memory/MemoryPool.h b/src/memory/MemoryPool.h index 1fc6564a..8d8d34f4 100644 --- a/src/memory/MemoryPool.h +++ b/src/memory/MemoryPool.h @@ -28,6 +28,9 @@ // Libraries #include "../constants.h" #include +#include +#include +#include // ReactPhysics3D namespace namespace reactphysics3d { @@ -40,7 +43,7 @@ namespace reactphysics3d { and deallocation. ------------------------------------------------------------------- */ -template // TODO : Check if we need to use a template here +template // TODO : Check if we need to use a template here class MemoryPool { private: @@ -54,6 +57,8 @@ class MemoryPool { struct Unit* pAllocatedLinkedList; // Pointer to the linked list of allocated memory units struct Unit* pFreeLinkedList; // Pointer to the linked list of free memory units size_t memorySize; // Total allocated memory in the pool + uint currentNbObjects; // Current number of objects in the pool + const uint initNbAllocatedObjects; // Number of objects allocated at the beginning (used for reallocation) public: MemoryPool(uint nbObjectsToAllocate) throw(std::bad_alloc); // Constructor @@ -64,6 +69,108 @@ class MemoryPool { }; +// Constructor +// Allocate a large block of memory in order to contain +// a given number of object of the template type T +template +MemoryPool::MemoryPool(uint nbObjectsToAllocate) throw(std::bad_alloc) + : initNbAllocatedObjects(nbObjectsToAllocate), currentNbObjects(0) { + pMemoryBlock = NULL; + pAllocatedLinkedList = NULL; + pFreeLinkedList = NULL; + + // Compute the total memory size that need to be allocated + memorySize = nbObjectsToAllocate * (sizeof(struct Unit) + sizeof(T)); + + // Allocate the whole memory block + pMemoryBlock = malloc(memorySize); + + // Check that the allocation didn't fail + if (!pMemoryBlock) throw std::bad_alloc(); + + // For each allocated memory unit + for (uint i=0; ipPrevious = NULL; + currentUnit->pNext = pFreeLinkedList; + + if (pFreeLinkedList) { + pFreeLinkedList->pPrevious = currentUnit; + } + + pFreeLinkedList = currentUnit; + } + +} + +// Destructor +// Deallocate the block of memory that has been allocated previously +template +MemoryPool::~MemoryPool() { + // Release the whole memory block + free(pMemoryBlock); +} + +// Return a pointer to an memory allocated location to store a new object +// This method does not allocate memory because it has already been done at the +// beginning but it returns a pointer to a location in the allocated block of +// memory where a new object can be stored +template +void* MemoryPool::allocateObject() { + // If no memory unit is available in the current allocated memory block + if (!pFreeLinkedList) { + // TODO : REALLOCATE MEMORY HERE + assert(false); + } + + assert(pFreeLinkedList); + struct Unit* currentUnit = pFreeLinkedList; + pFreeLinkedList = currentUnit->pNext; + if (pFreeLinkedList) { + pFreeLinkedList->pPrevious = NULL; + } + + currentUnit->pNext = pAllocatedLinkedList; + if (pAllocatedLinkedList) { + pAllocatedLinkedList->pPrevious = currentUnit; + } + pAllocatedLinkedList = currentUnit; + + currentNbObjects++; + + // Return a pointer to the allocated memory unit + return (void*)((char*)currentUnit + sizeof(struct Unit)); +} + +// Tell the pool that an object doesn't need to be store in the pool anymore +// This method does not deallocate memory because it will be done only at the +// end but it informs the memory pool that an object that was stored in the heap +// does not need to be stored anymore and therefore we can use the corresponding +// location in the pool for another object +template +void MemoryPool::freeObject(void* pObjectToFree) { + // The pointer location must be inside the memory block + assert(pMemoryBlockpNext; + if (pAllocatedLinkedList) { + pAllocatedLinkedList->pPrevious = NULL; + } + + currentUnit->pNext = pFreeLinkedList; + if (pFreeLinkedList) { + pFreeLinkedList->pPrevious = currentUnit; + } + pFreeLinkedList = currentUnit; + + currentNbObjects--; +} + + + } #endif