diff --git a/CHANGELOG.md b/CHANGELOG.md index f5c7bcd9..ff7b1ba9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Make possible for the user to get vertices, normals and triangle indices of a ConcaveMeshShape - Make possible for the user to get vertices and height values of the HeightFieldShape + - Make possible for the user to use a custom single frame and pool memory allocator ### Fixed diff --git a/CMakeLists.txt b/CMakeLists.txt index 389fadcf..410ff4c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,8 +148,8 @@ SET (REACTPHYSICS3D_HEADERS "src/mathematics/Vector3.h" "src/mathematics/Ray.h" "src/memory/MemoryAllocator.h" - "src/memory/PoolAllocator.h" - "src/memory/SingleFrameAllocator.h" + "src/memory/DefaultPoolAllocator.h" + "src/memory/DefaultSingleFrameAllocator.h" "src/memory/DefaultAllocator.h" "src/memory/MemoryManager.h" "src/containers/Stack.h" @@ -226,8 +226,8 @@ SET (REACTPHYSICS3D_SOURCES "src/mathematics/Transform.cpp" "src/mathematics/Vector2.cpp" "src/mathematics/Vector3.cpp" - "src/memory/PoolAllocator.cpp" - "src/memory/SingleFrameAllocator.cpp" + "src/memory/DefaultPoolAllocator.cpp" + "src/memory/DefaultSingleFrameAllocator.cpp" "src/memory/MemoryManager.cpp" "src/utils/Profiler.cpp" "src/utils/Logger.cpp" diff --git a/src/body/CollisionBody.h b/src/body/CollisionBody.h index 4123a055..ace349a6 100644 --- a/src/body/CollisionBody.h +++ b/src/body/CollisionBody.h @@ -42,7 +42,7 @@ class ProxyShape; class CollisionWorld; class CollisionShape; struct RaycastInfo; -class PoolAllocator; +class DefaultPoolAllocator; class Profiler; /// Enumeration for the type of a body diff --git a/src/collision/ContactManifold.h b/src/collision/ContactManifold.h index 3c2207e3..73f26a6e 100644 --- a/src/collision/ContactManifold.h +++ b/src/collision/ContactManifold.h @@ -38,7 +38,7 @@ class ContactManifoldInfo; struct ContactPointInfo; class CollisionBody; class ContactPoint; -class PoolAllocator; +class DefaultPoolAllocator; // Structure ContactManifoldListElement /** diff --git a/src/collision/broadphase/BroadPhaseAlgorithm.cpp b/src/collision/broadphase/BroadPhaseAlgorithm.cpp index 43a1122e..18618c4c 100644 --- a/src/collision/broadphase/BroadPhaseAlgorithm.cpp +++ b/src/collision/broadphase/BroadPhaseAlgorithm.cpp @@ -40,7 +40,7 @@ BroadPhaseAlgorithm::BroadPhaseAlgorithm(CollisionDetection& collisionDetection) mNbPotentialPairs(0), mNbAllocatedPotentialPairs(8), mCollisionDetection(collisionDetection) { - PoolAllocator& poolAllocator = collisionDetection.getMemoryManager().getPoolAllocator(); + MemoryAllocator& poolAllocator = collisionDetection.getMemoryManager().getPoolAllocator(); // Allocate memory for the array of potential overlapping pairs mPotentialPairs = static_cast(poolAllocator.allocate(mNbAllocatedPotentialPairs * sizeof(BroadPhasePair))); @@ -58,7 +58,7 @@ BroadPhaseAlgorithm::BroadPhaseAlgorithm(CollisionDetection& collisionDetection) BroadPhaseAlgorithm::~BroadPhaseAlgorithm() { // Get the memory pool allocatory - PoolAllocator& poolAllocator = mCollisionDetection.getMemoryManager().getPoolAllocator(); + MemoryAllocator& poolAllocator = mCollisionDetection.getMemoryManager().getPoolAllocator(); // Release the memory for the array of potential overlapping pairs poolAllocator.release(mPotentialPairs, mNbAllocatedPotentialPairs * sizeof(BroadPhasePair)); @@ -234,7 +234,7 @@ void BroadPhaseAlgorithm::computeOverlappingPairs(MemoryManager& memoryManager) // number of overlapping pairs if (mNbPotentialPairs < mNbAllocatedPotentialPairs / 4 && mNbPotentialPairs > 8) { - PoolAllocator& poolAllocator = mCollisionDetection.getMemoryManager().getPoolAllocator(); + MemoryAllocator& poolAllocator = mCollisionDetection.getMemoryManager().getPoolAllocator(); // Reduce the number of allocated potential overlapping pairs BroadPhasePair* oldPairs = mPotentialPairs; @@ -260,7 +260,7 @@ void BroadPhaseAlgorithm::addOverlappingNodes(int referenceNodeId, const LinkedL // If we need to allocate more memory for the array of potential overlapping pairs if (mNbPotentialPairs == mNbAllocatedPotentialPairs) { - PoolAllocator& poolAllocator = mCollisionDetection.getMemoryManager().getPoolAllocator(); + MemoryAllocator& poolAllocator = mCollisionDetection.getMemoryManager().getPoolAllocator(); // Allocate more memory for the array of potential pairs BroadPhasePair* oldPairs = mPotentialPairs; diff --git a/src/collision/narrowphase/NarrowPhaseAlgorithm.h b/src/collision/narrowphase/NarrowPhaseAlgorithm.h index e7cdff25..dbb5ce49 100644 --- a/src/collision/narrowphase/NarrowPhaseAlgorithm.h +++ b/src/collision/narrowphase/NarrowPhaseAlgorithm.h @@ -34,7 +34,7 @@ namespace reactphysics3d { class CollisionDetection; class Body; class ContactManifoldInfo; -class PoolAllocator; +class DefaultPoolAllocator; class OverlappingPair; struct NarrowPhaseInfo; struct ContactPointInfo; diff --git a/src/collision/shapes/CollisionShape.h b/src/collision/shapes/CollisionShape.h index 4e1206d3..1f4bb8ad 100644 --- a/src/collision/shapes/CollisionShape.h +++ b/src/collision/shapes/CollisionShape.h @@ -35,7 +35,7 @@ namespace reactphysics3d { // Declarations class Profiler; -class PoolAllocator; +class DefaultPoolAllocator; class AABB; class Transform; struct Ray; diff --git a/src/memory/PoolAllocator.cpp b/src/memory/DefaultPoolAllocator.cpp similarity index 95% rename from src/memory/PoolAllocator.cpp rename to src/memory/DefaultPoolAllocator.cpp index f73ab150..5d4f4ff0 100644 --- a/src/memory/PoolAllocator.cpp +++ b/src/memory/DefaultPoolAllocator.cpp @@ -24,7 +24,7 @@ ********************************************************************************/ // Libraries -#include "PoolAllocator.h" +#include "DefaultPoolAllocator.h" #include "MemoryManager.h" #include #include @@ -32,12 +32,12 @@ using namespace reactphysics3d; // Initialization of static variables -bool PoolAllocator::isMapSizeToHeadIndexInitialized = false; -size_t PoolAllocator::mUnitSizes[NB_HEAPS]; -int PoolAllocator::mMapSizeToHeapIndex[MAX_UNIT_SIZE + 1]; +bool DefaultPoolAllocator::isMapSizeToHeadIndexInitialized = false; +size_t DefaultPoolAllocator::mUnitSizes[NB_HEAPS]; +int DefaultPoolAllocator::mMapSizeToHeapIndex[MAX_UNIT_SIZE + 1]; // Constructor -PoolAllocator::PoolAllocator() { +DefaultPoolAllocator::DefaultPoolAllocator() { // Allocate some memory to manage the blocks mNbAllocatedMemoryBlocks = 64; @@ -79,7 +79,7 @@ PoolAllocator::PoolAllocator() { } // Destructor -PoolAllocator::~PoolAllocator() { +DefaultPoolAllocator::~DefaultPoolAllocator() { // Release the memory allocated for each block for (uint i=0; i #include @@ -32,26 +32,27 @@ using namespace reactphysics3d; // Constructor -SingleFrameAllocator::SingleFrameAllocator() - : mTotalSizeBytes(INIT_SINGLE_FRAME_ALLOCATOR_NB_BYTES), +DefaultSingleFrameAllocator::DefaultSingleFrameAllocator() + : mBaseMemoryAllocator(&MemoryManager::getBaseAllocator()), + mTotalSizeBytes(INIT_SINGLE_FRAME_ALLOCATOR_NB_BYTES), mCurrentOffset(0), mNbFramesTooMuchAllocated(0), mNeedToAllocatedMore(false) { // Allocate a whole block of memory at the beginning - mMemoryBufferStart = static_cast(MemoryManager::getBaseAllocator().allocate(mTotalSizeBytes)); + mMemoryBufferStart = static_cast(mBaseMemoryAllocator->allocate(mTotalSizeBytes)); assert(mMemoryBufferStart != nullptr); } // Destructor -SingleFrameAllocator::~SingleFrameAllocator() { +DefaultSingleFrameAllocator::~DefaultSingleFrameAllocator() { // Release the memory allocated at the beginning - MemoryManager::getBaseAllocator().release(mMemoryBufferStart, mTotalSizeBytes); + mBaseMemoryAllocator->release(mMemoryBufferStart, mTotalSizeBytes); } // Allocate memory of a given size (in bytes) and return a pointer to the // allocated memory. -void* SingleFrameAllocator::allocate(size_t size) { +void* DefaultSingleFrameAllocator::allocate(size_t size) { // Check that there is enough remaining memory in the buffer if (mCurrentOffset + size > mTotalSizeBytes) { @@ -60,7 +61,7 @@ void* SingleFrameAllocator::allocate(size_t size) { mNeedToAllocatedMore = true; // Return default memory allocation - return MemoryManager::getBaseAllocator().allocate(size); + return mBaseMemoryAllocator->allocate(size); } // Next available memory location @@ -74,19 +75,19 @@ void* SingleFrameAllocator::allocate(size_t size) { } // Release previously allocated memory. -void SingleFrameAllocator::release(void* pointer, size_t size) { +void DefaultSingleFrameAllocator::release(void* pointer, size_t size) { // If allocated memory is not within the single frame allocation range char* p = static_cast(pointer); if (p < mMemoryBufferStart || p > mMemoryBufferStart + mTotalSizeBytes) { // Use default deallocation - MemoryManager::getBaseAllocator().release(pointer, size); + mBaseMemoryAllocator->release(pointer, size); } } // Reset the marker of the current allocated memory -void SingleFrameAllocator::reset() { +void DefaultSingleFrameAllocator::reset() { // If too much memory is allocated if (mCurrentOffset < mTotalSizeBytes / 2) { @@ -96,14 +97,14 @@ void SingleFrameAllocator::reset() { if (mNbFramesTooMuchAllocated > NB_FRAMES_UNTIL_SHRINK) { // Release the memory allocated at the beginning - MemoryManager::getBaseAllocator().release(mMemoryBufferStart, mTotalSizeBytes); + mBaseMemoryAllocator->release(mMemoryBufferStart, mTotalSizeBytes); // Divide the total memory to allocate by two mTotalSizeBytes /= 2; if (mTotalSizeBytes == 0) mTotalSizeBytes = 1; // Allocate a whole block of memory at the beginning - mMemoryBufferStart = static_cast(MemoryManager::getBaseAllocator().allocate(mTotalSizeBytes)); + mMemoryBufferStart = static_cast(mBaseMemoryAllocator->allocate(mTotalSizeBytes)); assert(mMemoryBufferStart != nullptr); mNbFramesTooMuchAllocated = 0; @@ -117,13 +118,13 @@ void SingleFrameAllocator::reset() { if (mNeedToAllocatedMore) { // Release the memory allocated at the beginning - MemoryManager::getBaseAllocator().release(mMemoryBufferStart, mTotalSizeBytes); + mBaseMemoryAllocator->release(mMemoryBufferStart, mTotalSizeBytes); // Multiply the total memory to allocate by two mTotalSizeBytes *= 2; // Allocate a whole block of memory at the beginning - mMemoryBufferStart = static_cast(MemoryManager::getBaseAllocator().allocate(mTotalSizeBytes)); + mMemoryBufferStart = static_cast(mBaseMemoryAllocator->allocate(mTotalSizeBytes)); assert(mMemoryBufferStart != nullptr); mNeedToAllocatedMore = false; diff --git a/src/memory/SingleFrameAllocator.h b/src/memory/DefaultSingleFrameAllocator.h similarity index 87% rename from src/memory/SingleFrameAllocator.h rename to src/memory/DefaultSingleFrameAllocator.h index 599c0b65..65641129 100644 --- a/src/memory/SingleFrameAllocator.h +++ b/src/memory/DefaultSingleFrameAllocator.h @@ -33,12 +33,12 @@ /// ReactPhysics3D namespace namespace reactphysics3d { -// Class SingleFrameAllocator +// Class DefaultSingleFrameAllocator /** * This class represent a memory allocator used to efficiently allocate * memory on the heap that is used during a single frame. */ -class SingleFrameAllocator : public MemoryAllocator { +class DefaultSingleFrameAllocator : public SingleFrameAllocator { private : @@ -49,9 +49,11 @@ class SingleFrameAllocator : public MemoryAllocator { static const int NB_FRAMES_UNTIL_SHRINK = 120; /// Initial size (in bytes) of the single frame allocator - size_t INIT_SINGLE_FRAME_ALLOCATOR_NB_BYTES = 1048576; // 1Mb + static const size_t INIT_SINGLE_FRAME_ALLOCATOR_NB_BYTES = 1048576; // 1Mb // -------------------- Attributes -------------------- // + /// Cached memory allocator used on construction + MemoryAllocator* mBaseMemoryAllocator; /// Total size (in bytes) of memory of the allocator size_t mTotalSizeBytes; @@ -74,13 +76,13 @@ class SingleFrameAllocator : public MemoryAllocator { // -------------------- Methods -------------------- // /// Constructor - SingleFrameAllocator(); + DefaultSingleFrameAllocator(); /// Destructor - virtual ~SingleFrameAllocator() override; + virtual ~DefaultSingleFrameAllocator() override; /// Assignment operator - SingleFrameAllocator& operator=(SingleFrameAllocator& allocator) = default; + DefaultSingleFrameAllocator& operator=(DefaultSingleFrameAllocator& allocator) = default; /// Allocate memory of a given size (in bytes) virtual void* allocate(size_t size) override; @@ -89,7 +91,7 @@ class SingleFrameAllocator : public MemoryAllocator { virtual void release(void* pointer, size_t size) override; /// Reset the marker of the current allocated memory - virtual void reset(); + virtual void reset() override; }; } diff --git a/src/memory/MemoryAllocator.h b/src/memory/MemoryAllocator.h index 9811387b..cc0df8de 100644 --- a/src/memory/MemoryAllocator.h +++ b/src/memory/MemoryAllocator.h @@ -57,6 +57,33 @@ class MemoryAllocator { virtual void release(void* pointer, size_t size)=0; }; +/** + * Abstract class with the basic interface of all single frames memory allocators + */ +class SingleFrameAllocator : public MemoryAllocator{ + + public: + + /// Constructor + SingleFrameAllocator() = default; + + /// Destructor + virtual ~SingleFrameAllocator() override = default; + + /// Assignment operator + SingleFrameAllocator& operator=(SingleFrameAllocator& allocator) = default; + + /// Allocate memory of a given size (in bytes) and return a pointer to the + /// allocated memory. + virtual void* allocate(size_t size) override =0; + + /// Release previously allocated memory. + virtual void release(void* pointer, size_t size) override =0; + + /// Reset the marker of the current allocated memory + virtual void reset()=0; +}; + } #endif diff --git a/src/memory/MemoryManager.cpp b/src/memory/MemoryManager.cpp index 7dc80543..7427bcdd 100644 --- a/src/memory/MemoryManager.cpp +++ b/src/memory/MemoryManager.cpp @@ -30,5 +30,9 @@ using namespace reactphysics3d; // Static variables DefaultAllocator MemoryManager::mDefaultAllocator; +DefaultSingleFrameAllocator MemoryManager::mDefaultSingleFrameAllocator; +DefaultPoolAllocator MemoryManager::mDefaultPoolAllocator; MemoryAllocator* MemoryManager::mBaseAllocator = &mDefaultAllocator; +MemoryAllocator* MemoryManager::mPoolAllocator = &mDefaultPoolAllocator; +SingleFrameAllocator* MemoryManager::mSingleFrameAllocator = &mDefaultSingleFrameAllocator; diff --git a/src/memory/MemoryManager.h b/src/memory/MemoryManager.h index 65797218..b4269cbb 100644 --- a/src/memory/MemoryManager.h +++ b/src/memory/MemoryManager.h @@ -28,8 +28,9 @@ // Libraries #include "memory/DefaultAllocator.h" -#include "memory/PoolAllocator.h" -#include "memory/SingleFrameAllocator.h" +#include "memory/DefaultPoolAllocator.h" +#include "memory/MemoryAllocator.h" +#include "memory/DefaultSingleFrameAllocator.h" /// Namespace ReactPhysics3D namespace reactphysics3d { @@ -45,18 +46,24 @@ class MemoryAllocator; class MemoryManager { private: - + /// Default malloc/free memory allocator static DefaultAllocator mDefaultAllocator; + + /// Default single frame memory allocator + static DefaultSingleFrameAllocator mDefaultSingleFrameAllocator; + + /// Default pool memory allocator + static DefaultPoolAllocator mDefaultPoolAllocator; /// Pointer to the base memory allocator to use static MemoryAllocator* mBaseAllocator; - /// Memory pool allocator - PoolAllocator mPoolAllocator; - /// Single frame stack allocator - SingleFrameAllocator mSingleFrameAllocator; + static SingleFrameAllocator* mSingleFrameAllocator; + + /// Memory pool allocator + static MemoryAllocator* mPoolAllocator; public: @@ -80,17 +87,23 @@ class MemoryManager { void release(AllocationType allocationType, void* pointer, size_t size); /// Return the pool allocator - PoolAllocator& getPoolAllocator(); + MemoryAllocator& getPoolAllocator(); /// Return the single frame stack allocator SingleFrameAllocator& getSingleFrameAllocator(); /// Return the base memory allocator static MemoryAllocator& getBaseAllocator(); - + /// Set the base memory allocator static void setBaseAllocator(MemoryAllocator* memoryAllocator); + /// Set the single frame memory allocator + static void setSingleFrameAllocator(SingleFrameAllocator* singleFrameAllocator); + + /// Set the pool memory allocator + static void setPoolAllocator(MemoryAllocator* poolAllocator); + /// Reset the single frame allocator void resetFrameAllocator(); }; @@ -100,8 +113,8 @@ inline void* MemoryManager::allocate(AllocationType allocationType, size_t size) switch (allocationType) { case AllocationType::Base: return mBaseAllocator->allocate(size); - case AllocationType::Pool: return mPoolAllocator.allocate(size); - case AllocationType::Frame: return mSingleFrameAllocator.allocate(size); + case AllocationType::Pool: return mPoolAllocator->allocate(size); + case AllocationType::Frame: return mSingleFrameAllocator->allocate(size); } return nullptr; @@ -112,19 +125,19 @@ inline void MemoryManager::release(AllocationType allocationType, void* pointer, switch (allocationType) { case AllocationType::Base: mBaseAllocator->release(pointer, size); break; - case AllocationType::Pool: mPoolAllocator.release(pointer, size); break; - case AllocationType::Frame: mSingleFrameAllocator.release(pointer, size); break; + case AllocationType::Pool: mPoolAllocator->release(pointer, size); break; + case AllocationType::Frame: mSingleFrameAllocator->release(pointer, size); break; } } // Return the pool allocator -inline PoolAllocator& MemoryManager::getPoolAllocator() { - return mPoolAllocator; +inline MemoryAllocator& MemoryManager::getPoolAllocator() { + return *mPoolAllocator; } // Return the single frame stack allocator inline SingleFrameAllocator& MemoryManager::getSingleFrameAllocator() { - return mSingleFrameAllocator; + return *mSingleFrameAllocator; } // Return the base memory allocator @@ -137,9 +150,19 @@ inline void MemoryManager::setBaseAllocator(MemoryAllocator* baseAllocator) { mBaseAllocator = baseAllocator; } +// Set the base memory allocator +inline void MemoryManager::setSingleFrameAllocator(SingleFrameAllocator* singleFrameAllocator) { + mSingleFrameAllocator = singleFrameAllocator; +} + +// Set the pool memory allocator +inline void MemoryManager::setPoolAllocator(MemoryAllocator* poolAllocator) { + mPoolAllocator = poolAllocator; +} + // Reset the single frame allocator inline void MemoryManager::resetFrameAllocator() { - mSingleFrameAllocator.reset(); + mSingleFrameAllocator->reset(); } }