diff --git a/src/collision/CollisionDetection.cpp b/src/collision/CollisionDetection.cpp index 44e24810..e5359860 100644 --- a/src/collision/CollisionDetection.cpp +++ b/src/collision/CollisionDetection.cpp @@ -43,9 +43,10 @@ using namespace reactphysics3d; using namespace std; // Constructor -CollisionDetection::CollisionDetection(CollisionWorld* world) - : mWorld(world), mNarrowPhaseGJKAlgorithm(mMemoryPoolContactInfos), - mNarrowPhaseSphereVsSphereAlgorithm(mMemoryPoolContactInfos) { +CollisionDetection::CollisionDetection(CollisionWorld* world, MemoryAllocator& memoryAllocator) + : mWorld(world), mMemoryAllocator(memoryAllocator), + mNarrowPhaseGJKAlgorithm(memoryAllocator), + mNarrowPhaseSphereVsSphereAlgorithm(memoryAllocator) { // Create the broad-phase algorithm that will be used (Sweep and Prune with AABB) mBroadPhaseAlgorithm = new SweepAndPruneAlgorithm(*this); @@ -127,9 +128,9 @@ void CollisionDetection::computeNarrowPhase() { // Notify the world about the new narrow-phase contact mWorld->notifyNewContact(pair, contactInfo); - // Delete and remove the contact info from the memory pool + // Delete and remove the contact info from the memory allocator contactInfo->ContactInfo::~ContactInfo(); - mMemoryPoolContactInfos.freeObject(contactInfo); + mMemoryAllocator.release(contactInfo, sizeof(ContactInfo)); } } } @@ -142,7 +143,7 @@ void CollisionDetection::broadPhaseNotifyAddedOverlappingPair(BodyPair* addedPai bodyindexpair indexPair = addedPair->getBodiesIndexPair(); // Create the corresponding broad-phase pair object - BroadPhasePair* broadPhasePair = new (mMemoryPoolBroadPhasePairs.allocateObject()) + BroadPhasePair* broadPhasePair = new (mMemoryAllocator.allocate(sizeof(BroadPhasePair))) BroadPhasePair(addedPair->body1, addedPair->body2); assert(broadPhasePair != NULL); @@ -169,8 +170,8 @@ void CollisionDetection::broadPhaseNotifyRemovedOverlappingPair(BodyPair* remove // Notify the world about the removed broad-phase pair mWorld->notifyRemovedOverlappingPair(broadPhasePair); - // Remove the overlapping pair from the memory pool + // Remove the overlapping pair from the memory allocator broadPhasePair->BroadPhasePair::~BroadPhasePair(); - mMemoryPoolBroadPhasePairs.freeObject(broadPhasePair); + mMemoryAllocator.release(broadPhasePair, sizeof(BroadPhasePair)); mOverlappingPairs.erase(indexPair); } diff --git a/src/collision/CollisionDetection.h b/src/collision/CollisionDetection.h index d44d1b94..71dda4bf 100644 --- a/src/collision/CollisionDetection.h +++ b/src/collision/CollisionDetection.h @@ -30,9 +30,9 @@ #include "../body/CollisionBody.h" #include "broadphase/BroadPhaseAlgorithm.h" #include "BroadPhasePair.h" -#include "../memory/MemoryPool.h" #include "narrowphase/GJK/GJKAlgorithm.h" #include "narrowphase/SphereVsSphereAlgorithm.h" +#include "../memory/MemoryAllocator.h" #include "ContactInfo.h" #include <vector> #include <map> @@ -64,6 +64,9 @@ class CollisionDetection { /// Pointer to the physics world CollisionWorld* mWorld; + /// Memory allocator + MemoryAllocator& mMemoryAllocator; + /// Broad-phase overlapping pairs std::map<bodyindexpair, BroadPhasePair*> mOverlappingPairs; @@ -76,12 +79,6 @@ class CollisionDetection { /// Narrow-phase Sphere vs Sphere algorithm SphereVsSphereAlgorithm mNarrowPhaseSphereVsSphereAlgorithm; - /// Memory pool for contactinfo - MemoryPool<ContactInfo> mMemoryPoolContactInfos; - - /// Memory pool for broad-phase pairs - MemoryPool<BroadPhasePair> mMemoryPoolBroadPhasePairs; - // -------------------- Methods -------------------- // /// Private copy-constructor @@ -105,7 +102,7 @@ class CollisionDetection { // -------------------- Methods -------------------- // /// Constructor - CollisionDetection(CollisionWorld* world); + CollisionDetection(CollisionWorld* world, MemoryAllocator& memoryAllocator); /// Destructor ~CollisionDetection(); diff --git a/src/collision/narrowphase/EPA/EPAAlgorithm.cpp b/src/collision/narrowphase/EPA/EPAAlgorithm.cpp index 151a7f6c..d14aff7b 100644 --- a/src/collision/narrowphase/EPA/EPAAlgorithm.cpp +++ b/src/collision/narrowphase/EPA/EPAAlgorithm.cpp @@ -32,8 +32,8 @@ using namespace reactphysics3d; // Constructor -EPAAlgorithm::EPAAlgorithm(MemoryPool<ContactInfo>& memoryPoolContactInfos) - : mMemoryPoolContactInfos(memoryPoolContactInfos) { +EPAAlgorithm::EPAAlgorithm(MemoryAllocator& memoryAllocator) + : mMemoryAllocator(memoryAllocator) { } @@ -400,7 +400,7 @@ bool EPAAlgorithm::computePenetrationDepthAndContactPoints(const Simplex& simple assert(penetrationDepth > 0.0); // Create the contact info object - contactInfo = new (mMemoryPoolContactInfos.allocateObject()) ContactInfo(normal, + contactInfo = new (mMemoryAllocator.allocate(sizeof(ContactInfo))) ContactInfo(normal, penetrationDepth, pALocal, pBLocal); diff --git a/src/collision/narrowphase/EPA/EPAAlgorithm.h b/src/collision/narrowphase/EPA/EPAAlgorithm.h index 4fcdd3be..c9edc3b9 100644 --- a/src/collision/narrowphase/EPA/EPAAlgorithm.h +++ b/src/collision/narrowphase/EPA/EPAAlgorithm.h @@ -32,7 +32,7 @@ #include "../../ContactInfo.h" #include "../../../mathematics/mathematics.h" #include "TriangleEPA.h" -#include "../../../memory/MemoryPool.h" +#include "../../../memory/MemoryAllocator.h" #include <algorithm> /// ReactPhysics3D namespace @@ -85,8 +85,8 @@ class EPAAlgorithm { // -------------------- Attributes -------------------- // - /// Reference to the memory pool - MemoryPool<ContactInfo>& mMemoryPoolContactInfos; + /// Reference to the memory allocator + MemoryAllocator& mMemoryAllocator; /// Triangle comparison operator TriangleComparison mTriangleComparison; @@ -112,7 +112,7 @@ class EPAAlgorithm { // -------------------- Methods -------------------- // /// Constructor - EPAAlgorithm(MemoryPool<ContactInfo>& memoryPoolContactInfos); + EPAAlgorithm(MemoryAllocator& memoryAllocator); /// Destructor ~EPAAlgorithm(); diff --git a/src/collision/narrowphase/GJK/GJKAlgorithm.cpp b/src/collision/narrowphase/GJK/GJKAlgorithm.cpp index 7e6814d1..b03f3953 100644 --- a/src/collision/narrowphase/GJK/GJKAlgorithm.cpp +++ b/src/collision/narrowphase/GJK/GJKAlgorithm.cpp @@ -37,8 +37,8 @@ using namespace reactphysics3d; // Constructor -GJKAlgorithm::GJKAlgorithm(MemoryPool<ContactInfo>& memoryPoolContactInfos) - :NarrowPhaseAlgorithm(memoryPoolContactInfos), mAlgoEPA(memoryPoolContactInfos) { +GJKAlgorithm::GJKAlgorithm(MemoryAllocator& memoryAllocator) + :NarrowPhaseAlgorithm(memoryAllocator), mAlgoEPA(memoryAllocator) { } @@ -137,7 +137,7 @@ bool GJKAlgorithm::testCollision(const CollisionShape* collisionShape1, if (penetrationDepth <= 0.0) return false; // Create the contact info object - contactInfo = new (mMemoryPoolContactInfos.allocateObject()) ContactInfo(normal, + contactInfo = new (mMemoryAllocator.allocate(sizeof(ContactInfo))) ContactInfo(normal, penetrationDepth, pA, pB); @@ -169,7 +169,7 @@ bool GJKAlgorithm::testCollision(const CollisionShape* collisionShape1, if (penetrationDepth <= 0.0) return false; // Create the contact info object - contactInfo = new (mMemoryPoolContactInfos.allocateObject()) ContactInfo(normal, + contactInfo = new (mMemoryAllocator.allocate(sizeof(ContactInfo))) ContactInfo(normal, penetrationDepth, pA, pB); @@ -199,7 +199,7 @@ bool GJKAlgorithm::testCollision(const CollisionShape* collisionShape1, if (penetrationDepth <= 0.0) return false; // Create the contact info object - contactInfo = new (mMemoryPoolContactInfos.allocateObject()) ContactInfo(normal, + contactInfo = new (mMemoryAllocator.allocate(sizeof(ContactInfo))) ContactInfo(normal, penetrationDepth, pA, pB); @@ -236,7 +236,7 @@ bool GJKAlgorithm::testCollision(const CollisionShape* collisionShape1, if (penetrationDepth <= 0.0) return false; // Create the contact info object - contactInfo = new (mMemoryPoolContactInfos.allocateObject()) ContactInfo(normal, + contactInfo = new (mMemoryAllocator.allocate(sizeof(ContactInfo))) ContactInfo(normal, penetrationDepth, pA, pB); diff --git a/src/collision/narrowphase/GJK/GJKAlgorithm.h b/src/collision/narrowphase/GJK/GJKAlgorithm.h index 6214d825..fc4af52e 100644 --- a/src/collision/narrowphase/GJK/GJKAlgorithm.h +++ b/src/collision/narrowphase/GJK/GJKAlgorithm.h @@ -85,7 +85,7 @@ class GJKAlgorithm : public NarrowPhaseAlgorithm { // -------------------- Methods -------------------- // /// Constructor - GJKAlgorithm(MemoryPool<ContactInfo>& memoryPoolContactInfos); + GJKAlgorithm(MemoryAllocator& memoryAllocator); /// Destructor ~GJKAlgorithm(); diff --git a/src/collision/narrowphase/NarrowPhaseAlgorithm.cpp b/src/collision/narrowphase/NarrowPhaseAlgorithm.cpp index 0b214ea0..91a1e4d5 100644 --- a/src/collision/narrowphase/NarrowPhaseAlgorithm.cpp +++ b/src/collision/narrowphase/NarrowPhaseAlgorithm.cpp @@ -30,8 +30,8 @@ using namespace reactphysics3d; // Constructor -NarrowPhaseAlgorithm::NarrowPhaseAlgorithm(MemoryPool<ContactInfo>& memoryPool) - :mMemoryPoolContactInfos(memoryPool), mCurrentOverlappingPair(NULL) { +NarrowPhaseAlgorithm::NarrowPhaseAlgorithm(MemoryAllocator& memoryAllocator) + :mMemoryAllocator(memoryAllocator), mCurrentOverlappingPair(NULL) { } diff --git a/src/collision/narrowphase/NarrowPhaseAlgorithm.h b/src/collision/narrowphase/NarrowPhaseAlgorithm.h index 8dea2ca8..d68f3f28 100644 --- a/src/collision/narrowphase/NarrowPhaseAlgorithm.h +++ b/src/collision/narrowphase/NarrowPhaseAlgorithm.h @@ -30,7 +30,7 @@ #include "../../body/Body.h" #include "../ContactInfo.h" #include "../broadphase/PairManager.h" -#include "../../memory/MemoryPool.h" +#include "../../memory/MemoryAllocator.h" #include "../BroadPhasePair.h" @@ -50,8 +50,8 @@ class NarrowPhaseAlgorithm { // -------------------- Attributes -------------------- // - /// Reference to the memory pool - MemoryPool<ContactInfo>& mMemoryPoolContactInfos; + /// Reference to the memory allocator + MemoryAllocator& mMemoryAllocator; /// Overlapping pair of the bodies currently tested for collision BroadPhasePair* mCurrentOverlappingPair; @@ -69,7 +69,7 @@ class NarrowPhaseAlgorithm { // -------------------- Methods -------------------- // /// Constructor - NarrowPhaseAlgorithm(MemoryPool<ContactInfo>& memoryPool); + NarrowPhaseAlgorithm(MemoryAllocator& memoryAllocator); /// Destructor virtual ~NarrowPhaseAlgorithm(); diff --git a/src/collision/narrowphase/SphereVsSphereAlgorithm.cpp b/src/collision/narrowphase/SphereVsSphereAlgorithm.cpp index cded8912..2f950e04 100644 --- a/src/collision/narrowphase/SphereVsSphereAlgorithm.cpp +++ b/src/collision/narrowphase/SphereVsSphereAlgorithm.cpp @@ -31,8 +31,8 @@ using namespace reactphysics3d; // Constructor -SphereVsSphereAlgorithm::SphereVsSphereAlgorithm(MemoryPool<ContactInfo>& memoryPoolContactInfos) - :NarrowPhaseAlgorithm(memoryPoolContactInfos) { +SphereVsSphereAlgorithm::SphereVsSphereAlgorithm(MemoryAllocator& memoryAllocator) + :NarrowPhaseAlgorithm(memoryAllocator) { } @@ -69,7 +69,7 @@ bool SphereVsSphereAlgorithm::testCollision(const CollisionShape* collisionShape decimal penetrationDepth = sumRadius - std::sqrt(squaredDistanceBetweenCenters); // Create the contact info object - contactInfo = new (mMemoryPoolContactInfos.allocateObject()) ContactInfo( + contactInfo = new (mMemoryAllocator.allocate(sizeof(ContactInfo))) ContactInfo( vectorBetweenCenters.getUnit(), penetrationDepth, intersectionOnBody1, intersectionOnBody2); diff --git a/src/collision/narrowphase/SphereVsSphereAlgorithm.h b/src/collision/narrowphase/SphereVsSphereAlgorithm.h index bb966df1..1c50fb1f 100644 --- a/src/collision/narrowphase/SphereVsSphereAlgorithm.h +++ b/src/collision/narrowphase/SphereVsSphereAlgorithm.h @@ -57,7 +57,7 @@ class SphereVsSphereAlgorithm : public NarrowPhaseAlgorithm { // -------------------- Methods -------------------- // /// Constructor - SphereVsSphereAlgorithm(MemoryPool<ContactInfo>& memoryPoolContactInfos); + SphereVsSphereAlgorithm(MemoryAllocator& memoryAllocator); /// Destructor virtual ~SphereVsSphereAlgorithm(); diff --git a/src/constraint/ContactPoint.h b/src/constraint/ContactPoint.h index e501e036..0900d480 100644 --- a/src/constraint/ContactPoint.h +++ b/src/constraint/ContactPoint.h @@ -32,7 +32,6 @@ #include "../body/RigidBody.h" #include "../configuration.h" #include "../mathematics/mathematics.h" -#include "../memory/MemoryPool.h" #include "../configuration.h" #if defined(VISUAL_DEBUG) diff --git a/src/engine/CollisionWorld.cpp b/src/engine/CollisionWorld.cpp index af7eb189..39b9dc74 100644 --- a/src/engine/CollisionWorld.cpp +++ b/src/engine/CollisionWorld.cpp @@ -32,7 +32,8 @@ using namespace reactphysics3d; using namespace std; // Constructor -CollisionWorld::CollisionWorld() : mCollisionDetection(this), mCurrentBodyID(0) { +CollisionWorld::CollisionWorld() + : mCollisionDetection(this, mMemoryAllocator), mCurrentBodyID(0) { } // Destructor @@ -75,7 +76,7 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform, assert(bodyID < std::numeric_limits<reactphysics3d::bodyindex>::max()); // Create the collision body - CollisionBody* collisionBody = new (mMemoryPoolCollisionBodies.allocateObject()) + CollisionBody* collisionBody = new (mMemoryAllocator.allocate(sizeof(CollisionBody))) CollisionBody(transform, collisionShape, bodyID); assert(collisionBody != NULL); @@ -105,8 +106,8 @@ void CollisionWorld::destroyCollisionBody(CollisionBody* collisionBody) { // Remove the collision body from the list of bodies mBodies.erase(collisionBody); // TODO : Maybe use a set to make this faster - // Free the object from the memory pool - mMemoryPoolCollisionBodies.freeObject(collisionBody); + // Free the object from the memory allocator + mMemoryAllocator.release(collisionBody, sizeof(CollisionBody)); } // Return the next available body ID diff --git a/src/engine/CollisionWorld.h b/src/engine/CollisionWorld.h index 4a929a3a..00de6cdf 100644 --- a/src/engine/CollisionWorld.h +++ b/src/engine/CollisionWorld.h @@ -37,7 +37,7 @@ #include "../collision/CollisionDetection.h" #include "../constraint/Constraint.h" #include "../constraint/ContactPoint.h" -#include "../memory/MemoryPool.h" +#include "../memory/MemoryAllocator.h" /// Namespace reactphysics3d namespace reactphysics3d { @@ -66,12 +66,12 @@ class CollisionWorld { /// Current body ID bodyindex mCurrentBodyID; - /// Memory pool - MemoryPool<CollisionBody> mMemoryPoolCollisionBodies; - /// List of free ID for rigid bodies std::vector<luint> mFreeBodiesIDs; + /// Memory allocator + MemoryAllocator mMemoryAllocator; + // -------------------- Methods -------------------- // /// Private copy-constructor diff --git a/src/engine/ContactManifold.cpp b/src/engine/ContactManifold.cpp index be08a488..69a67e97 100644 --- a/src/engine/ContactManifold.cpp +++ b/src/engine/ContactManifold.cpp @@ -31,10 +31,10 @@ using namespace reactphysics3d; // Constructor ContactManifold::ContactManifold(Body* const body1, Body* const body2, - MemoryPool<ContactPoint>& memoryPoolContacts) + MemoryAllocator& memoryAllocator) : mBody1(body1), mBody2(body2), mNbContactPoints(0), mFrictionImpulse1(0.0), mFrictionImpulse2(0.0), mFrictionTwistImpulse(0.0), - mMemoryPoolContacts(memoryPoolContacts) { + mMemoryAllocator(memoryAllocator) { } @@ -57,7 +57,7 @@ void ContactManifold::addContactPoint(ContactPoint* contact) { // Delete the new contact contact->ContactPoint::~ContactPoint(); - mMemoryPoolContacts.freeObject(contact); + mMemoryAllocator.release(contact, sizeof(ContactPoint)); //removeContact(i); return; @@ -82,10 +82,10 @@ void ContactManifold::removeContactPoint(uint index) { assert(index < mNbContactPoints); assert(mNbContactPoints > 0); - // Call the destructor explicitly and tell the memory pool that + // Call the destructor explicitly and tell the memory allocator that // the corresponding memory block is now free mContactPoints[index]->ContactPoint::~ContactPoint(); - mMemoryPoolContacts.freeObject(mContactPoints[index]); + mMemoryAllocator.release(mContactPoints[index], sizeof(ContactPoint)); // If we don't remove the last index if (index < mNbContactPoints - 1) { @@ -243,10 +243,10 @@ int ContactManifold::getMaxArea(decimal area0, decimal area1, decimal area2, dec void ContactManifold::clear() { for (uint i=0; i<mNbContactPoints; i++) { - // Call the destructor explicitly and tell the memory pool that + // Call the destructor explicitly and tell the memory allocator that // the corresponding memory block is now free mContactPoints[i]->ContactPoint::~ContactPoint(); - mMemoryPoolContacts.freeObject(mContactPoints[i]); + mMemoryAllocator.release(mContactPoints[i], sizeof(ContactPoint)); } mNbContactPoints = 0; } diff --git a/src/engine/ContactManifold.h b/src/engine/ContactManifold.h index 02ffbf63..68c1d2f3 100644 --- a/src/engine/ContactManifold.h +++ b/src/engine/ContactManifold.h @@ -30,6 +30,7 @@ #include <vector> #include "../body/Body.h" #include "../constraint/ContactPoint.h" +#include "../memory/MemoryAllocator.h" /// ReactPhysics3D namespace namespace reactphysics3d { @@ -85,8 +86,8 @@ class ContactManifold { /// Twist friction constraint accumulated impulse decimal mFrictionTwistImpulse; - /// Reference to the memory pool with the contacts - MemoryPool<ContactPoint>& mMemoryPoolContacts; + /// Reference to the memory allocator + MemoryAllocator& mMemoryAllocator; // -------------------- Methods -------------------- // @@ -116,8 +117,7 @@ class ContactManifold { // -------------------- Methods -------------------- // /// Constructor - ContactManifold(Body* const mBody1, Body* const mBody2, - MemoryPool<ContactPoint>& mMemoryPoolContacts); + ContactManifold(Body* const mBody1, Body* const mBody2, MemoryAllocator& memoryAllocator); /// Destructor ~ContactManifold(); diff --git a/src/engine/DynamicsWorld.cpp b/src/engine/DynamicsWorld.cpp index 48940f82..27184f98 100644 --- a/src/engine/DynamicsWorld.cpp +++ b/src/engine/DynamicsWorld.cpp @@ -47,7 +47,7 @@ DynamicsWorld::~DynamicsWorld() { for (it = mOverlappingPairs.begin(); it != mOverlappingPairs.end(); it++) { // Delete the overlapping pair (*it).second->OverlappingPair::~OverlappingPair(); - mMemoryPoolOverlappingPairs.freeObject((*it).second); + mMemoryAllocator.release((*it).second, sizeof(OverlappingPair)); } // Free the allocated memory for the constrained velocities @@ -267,7 +267,8 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform, decimal ma assert(bodyID < std::numeric_limits<reactphysics3d::bodyindex>::max()); // Create the rigid body - RigidBody* rigidBody = new (mMemoryPoolRigidBodies.allocateObject()) RigidBody(transform, mass, + RigidBody* rigidBody = new (mMemoryAllocator.allocate(sizeof(RigidBody))) RigidBody(transform, + mass, inertiaTensorLocal, collisionShape, bodyID); @@ -300,8 +301,8 @@ void DynamicsWorld::destroyRigidBody(RigidBody* rigidBody) { mBodies.erase(rigidBody); mRigidBodies.erase(rigidBody); - // Free the object from the memory pool - mMemoryPoolRigidBodies.freeObject(rigidBody); + // Free the object from the memory allocator + mMemoryAllocator.release(rigidBody, sizeof(RigidBody)); } // Remove all constraints in the physics world @@ -316,8 +317,8 @@ void DynamicsWorld::notifyAddedOverlappingPair(const BroadPhasePair* addedPair) bodyindexpair indexPair = addedPair->getBodiesIndexPair(); // Add the pair into the set of overlapping pairs (if not there yet) - OverlappingPair* newPair = new (mMemoryPoolOverlappingPairs.allocateObject()) OverlappingPair( - addedPair->body1, addedPair->body2, mMemoryPoolContacts); + OverlappingPair* newPair = new (mMemoryAllocator.allocate(sizeof(OverlappingPair))) OverlappingPair( + addedPair->body1, addedPair->body2, mMemoryAllocator); assert(newPair != NULL); std::pair<map<bodyindexpair, OverlappingPair*>::iterator, bool> check = mOverlappingPairs.insert(make_pair(indexPair, newPair)); @@ -330,9 +331,9 @@ void DynamicsWorld::notifyRemovedOverlappingPair(const BroadPhasePair* removedPa // Get the pair of body index std::pair<bodyindex, bodyindex> indexPair = removedPair->getBodiesIndexPair(); - // Remove the overlapping pair from the memory pool + // Remove the overlapping pair from the memory allocator mOverlappingPairs.find(indexPair)->second->OverlappingPair::~OverlappingPair(); - mMemoryPoolOverlappingPairs.freeObject(mOverlappingPairs[indexPair]); + mMemoryAllocator.release(mOverlappingPairs[indexPair], sizeof(OverlappingPair)); mOverlappingPairs.erase(indexPair); } @@ -347,7 +348,8 @@ void DynamicsWorld::notifyNewContact(const BroadPhasePair* broadPhasePair, assert(rigidBody2 != NULL); // Create a new contact - ContactPoint* contact = new (mMemoryPoolContacts.allocateObject()) ContactPoint(rigidBody1, + ContactPoint* contact = new (mMemoryAllocator.allocate(sizeof(ContactPoint))) ContactPoint( + rigidBody1, rigidBody2, contactInfo); assert(contact != NULL); diff --git a/src/engine/DynamicsWorld.h b/src/engine/DynamicsWorld.h index 03abe3f8..fb66aa7b 100644 --- a/src/engine/DynamicsWorld.h +++ b/src/engine/DynamicsWorld.h @@ -73,15 +73,6 @@ class DynamicsWorld : public CollisionWorld { /// True if the gravity force is on bool mIsGravityOn; - /// Memory pool for the overlapping pairs - MemoryPool<OverlappingPair> mMemoryPoolOverlappingPairs; - - /// Memory pool for rigid bodies memory allocation - MemoryPool<RigidBody> mMemoryPoolRigidBodies; - - /// Memory pool for the contacts - MemoryPool<ContactPoint> mMemoryPoolContacts; - /// Array of constrained linear velocities (state of the linear velocities /// after solving the constraints) std::vector<Vector3> mConstrainedLinearVelocities; diff --git a/src/engine/OverlappingPair.cpp b/src/engine/OverlappingPair.cpp index 8ca9b511..69a459bb 100644 --- a/src/engine/OverlappingPair.cpp +++ b/src/engine/OverlappingPair.cpp @@ -31,8 +31,8 @@ using namespace reactphysics3d; // Constructor OverlappingPair::OverlappingPair(CollisionBody* body1, CollisionBody* body2, - MemoryPool<ContactPoint>& memoryPoolContacts) - : mBody1(body1), mBody2(body2), mContactManifold(body1, body2, memoryPoolContacts), + MemoryAllocator &memoryAllocator) + : mBody1(body1), mBody2(body2), mContactManifold(body1, body2, memoryAllocator), mCachedSeparatingAxis(1.0, 1.0, 1.0) { } diff --git a/src/engine/OverlappingPair.h b/src/engine/OverlappingPair.h index 36beba56..b3c16880 100644 --- a/src/engine/OverlappingPair.h +++ b/src/engine/OverlappingPair.h @@ -72,7 +72,7 @@ class OverlappingPair { /// Constructor OverlappingPair(CollisionBody* body1, CollisionBody* body2, - MemoryPool<ContactPoint>& memoryPoolContacts); + MemoryAllocator& memoryAllocator); /// Destructor ~OverlappingPair(); diff --git a/src/memory/MemoryAllocator.cpp b/src/memory/MemoryAllocator.cpp index 073255e3..e715a157 100644 --- a/src/memory/MemoryAllocator.cpp +++ b/src/memory/MemoryAllocator.cpp @@ -25,24 +25,169 @@ // Libraries #include "MemoryAllocator.h" +#include <cstdlib> +#include <cassert> + +using namespace reactphysics3d; + +// Initialization of static variables +bool MemoryAllocator::isMapSizeToHeadIndexInitialized = false; +size_t MemoryAllocator::mUnitSizes[NB_HEAPS]; +int MemoryAllocator::mMapSizeToHeapIndex[MAX_UNIT_SIZE + 1]; // Constructor MemoryAllocator::MemoryAllocator() { + // Allocate some memory to manage the blocks + mNbAllocatedMemoryBlocks = 64; + mNbCurrentMemoryBlocks = 0; + const size_t sizeToAllocate = mNbAllocatedMemoryBlocks * sizeof(MemoryBlock); + mMemoryBlocks = (MemoryBlock*) malloc(sizeToAllocate); + memset(mMemoryBlocks, NULL, sizeToAllocate); + memset(mFreeMemoryUnits, NULL, sizeof(mFreeMemoryUnits)); + +#ifndef NDEBUG + mNbTimesAllocateMethodCalled = 0; +#endif + + // If the mMapSizeToHeapIndex has not been initialized yet + if (!isMapSizeToHeadIndexInitialized) { + + // Initialize the array that contains the sizes the memory units that will + // be allocated in each different heap + for (uint i=0; i < NB_HEAPS; i++) { + mUnitSizes[i] = (i+1) * 8; + } + + // Initialize the lookup table that maps the size to allocated to the + // corresponding heap we will use for the allocation + uint j = 0; + mMapSizeToHeapIndex[0] = -1; // This element should not be used + for (uint i=1; i <= MAX_UNIT_SIZE; i++) { + if (i <= mUnitSizes[j]) { + mMapSizeToHeapIndex[i] = j; + } + else { + j++; + mMapSizeToHeapIndex[i] = j; + } + } + + isMapSizeToHeadIndexInitialized = true; + } } // Destructor MemoryAllocator::~MemoryAllocator() { + // Release the memory allocated for each block + for (uint i=0; i<mNbCurrentMemoryBlocks; i++) { + free(mMemoryBlocks[i].memoryUnits); + } + + free(mMemoryBlocks); + +#ifndef NDEBUG + // Check that the allocate() and release() methods have been called the same + // number of times to avoid memory leaks. + assert(mNbTimesAllocateMethodCalled == 0); +#endif } // Allocate memory of a given size (in bytes) and return a pointer to the // allocated memory. -void* MemoryAllocator::allocate(uint size) { +void* MemoryAllocator::allocate(size_t size) { + // We cannot allocate zero bytes + if (size == 0) return NULL; + +#ifndef NDEBUG + mNbTimesAllocateMethodCalled++; +#endif + + // If we need to allocate more than the maximum memory unit size + if (size > MAX_UNIT_SIZE) { + + // Allocate memory using standard malloc() function + return malloc(size); + } + + // Get the index of the heap that will take care of the allocation request + int indexHeap = mMapSizeToHeapIndex[size]; + assert(indexHeap >= 0 && indexHeap < NB_HEAPS); + + // If there still are free memory units in the corresponding heap + if (mFreeMemoryUnits[indexHeap] != NULL) { + + // Return a pointer to the memory unit + MemoryUnit* unit = mFreeMemoryUnits[indexHeap]; + mFreeMemoryUnits[indexHeap] = unit->nextUnit; + return unit; + } + else { // If there is no more free memory units in the corresponding heap + + // If we need to allocate more memory to containsthe blocks + if (mNbCurrentMemoryBlocks == mNbAllocatedMemoryBlocks) { + + // Allocate more memory to contain the blocks + MemoryBlock* currentMemoryBlocks = mMemoryBlocks; + mNbAllocatedMemoryBlocks += 64; + mMemoryBlocks = (MemoryBlock*) malloc(mNbAllocatedMemoryBlocks * sizeof(MemoryBlock)); + memcpy(mMemoryBlocks, currentMemoryBlocks,mNbCurrentMemoryBlocks * sizeof(MemoryBlock)); + memset(mMemoryBlocks + mNbCurrentMemoryBlocks, 0, 64 * sizeof(MemoryBlock)); + free(currentMemoryBlocks); + } + + // Allocate a new memory blocks for the corresponding heap and divide it in many + // memory units + MemoryBlock* newBlock = mMemoryBlocks + mNbCurrentMemoryBlocks; + newBlock->memoryUnits = (MemoryUnit*) malloc(BLOCK_SIZE); + assert(newBlock->memoryUnits != NULL); + size_t unitSize = mUnitSizes[indexHeap]; + uint nbUnits = BLOCK_SIZE / unitSize; + assert(nbUnits * unitSize <= BLOCK_SIZE); + for (size_t i=0; i < nbUnits - 1; i++) { + MemoryUnit* unit = (MemoryUnit*) ((size_t)newBlock->memoryUnits + unitSize * i); + MemoryUnit* nextUnit = (MemoryUnit*) ((size_t)newBlock->memoryUnits + unitSize * (i + 1)); + unit->nextUnit = nextUnit; + } + MemoryUnit* lastUnit = (MemoryUnit*) ((size_t)newBlock->memoryUnits + unitSize * (nbUnits - 1)); + lastUnit->nextUnit = NULL; + + // Add the new allocated block into the list of free memory units in the heap + mFreeMemoryUnits[indexHeap] = newBlock->memoryUnits->nextUnit; + mNbCurrentMemoryBlocks++; + + // Return the pointer to the first memory unit of the new allocated block + return newBlock->memoryUnits; + } } -// Free previously allocated memory. -void MemoryAllocator::free(void* pointer) { +// Release previously allocated memory. +void MemoryAllocator::release(void* pointer, size_t size) { + // Cannot release a 0-byte allocated memory + if (size == 0) return; + +#ifndef NDEBUG + mNbTimesAllocateMethodCalled--; +#endif + + // If the size is larger than the maximum memory unit size + if (size > MAX_UNIT_SIZE) { + + // Release the memory using the standard free() function + free(pointer); + return; + } + + // Get the index of the heap that has handled the corresponding allocation request + int indexHeap = mMapSizeToHeapIndex[size]; + assert(indexHeap >= 0 && indexHeap < NB_HEAPS); + + // Insert the released memory unit into the list of free memory units of the + // corresponding heap + MemoryUnit* releasedUnit = (MemoryUnit*) pointer; + releasedUnit->nextUnit = mFreeMemoryUnits[indexHeap]; + mFreeMemoryUnits[indexHeap] = releasedUnit; } diff --git a/src/memory/MemoryAllocator.h b/src/memory/MemoryAllocator.h index 3b380066..8ef90e14 100644 --- a/src/memory/MemoryAllocator.h +++ b/src/memory/MemoryAllocator.h @@ -27,20 +27,99 @@ #define MEMORY_ALLOCATOR_H // Libraries +#include "../configuration.h" + +/// ReactPhysics3D namespace +namespace reactphysics3d { // Class MemoryAllocator /** * This class is used to efficiently allocate memory on the heap. - * It allows us to allocate small blocks of memory (smaller than 1024 bytes) - * efficiently. This implementation is based on the small block allocator + * It allows us to allocate small blocks of memory (smaller or equal to 1024 bytes) + * efficiently. This implementation is inspired by the small block allocator * described here : http://www.codeproject.com/useritems/Small_Block_Allocator.asp */ class MemoryAllocator { private : + // -------------------- Internal Classes -------------------- // + + // Structure MemoryUnit + /** + * Represent a memory unit that is used for a single memory allocation + * request. + */ + struct MemoryUnit { + + public : + + // -------------------- Attributes -------------------- // + + /// Pointer to the next memory unit inside a memory block + MemoryUnit* nextUnit; + + }; + + // Structure MemoryBlock + /** + * A memory block is a large piece of memory that is allocated once and that + * will contain multiple memory unity. + */ + struct MemoryBlock { + + public : + + /// Pointer to the first element of a linked-list of memory unity. + MemoryUnit* memoryUnits; + }; + + // -------------------- Constants -------------------- // + + /// Number of heaps + static const uint NB_HEAPS = 128; + + /// Maximum memory unit size. An allocation request of a size smaller or equal to + /// this size will be handled using the small block allocator. However, for an + /// allocation request larger than the maximum block size, the standard malloc() + /// will be used. + static const size_t MAX_UNIT_SIZE = 1024; + + /// Size a memory chunk + static const size_t BLOCK_SIZE = 16 * MAX_UNIT_SIZE; + // -------------------- Attributes -------------------- // + /// Size of the memory units that each heap is responsible to allocate + static size_t mUnitSizes[NB_HEAPS]; + + /// Lookup table that mape size to allocate to the index of the + /// corresponding heap we will use for the allocation. + static int mMapSizeToHeapIndex[MAX_UNIT_SIZE + 1]; + + /// True if the mMapSizeToHeapIndex array has already been initialized + static bool isMapSizeToHeadIndexInitialized; + + /// Pointers to the first free memory unit for each heap + MemoryUnit* mFreeMemoryUnits[NB_HEAPS]; + + /// All the allocated memory blocks + MemoryBlock* mMemoryBlocks; + + /// Number of allocated memory blocks + uint mNbAllocatedMemoryBlocks; + + /// Current number of used memory blocks + uint mNbCurrentMemoryBlocks; + +#ifndef NDEBUG + /// This variable is incremented by one when the allocate() method has been + /// called and decreased by one when the release() method has been called. + /// This variable is used in debug mode to check that the allocate() and release() + /// methods are called the same number of times + int mNbTimesAllocateMethodCalled; +#endif + public : // -------------------- Methods -------------------- // @@ -53,11 +132,13 @@ class MemoryAllocator { /// Allocate memory of a given size (in bytes) and return a pointer to the /// allocated memory. - void* allocate(uint size); + void* allocate(size_t size); - /// Free previously allocated memory. - void free(void* pointer); + /// Release previously allocated memory. + void release(void* pointer, size_t size); }; +} + #endif diff --git a/src/memory/MemoryPool.h b/src/memory/MemoryPool.h deleted file mode 100644 index 1a0ff546..00000000 --- a/src/memory/MemoryPool.h +++ /dev/null @@ -1,283 +0,0 @@ -/******************************************************************************** -* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ * -* Copyright (c) 2010-2013 Daniel Chappuis * -********************************************************************************* -* * -* This software is provided 'as-is', without any express or implied warranty. * -* In no event will the authors be held liable for any damages arising from the * -* use of this software. * -* * -* Permission is granted to anyone to use this software for any purpose, * -* including commercial applications, and to alter it and redistribute it * -* freely, subject to the following restrictions: * -* * -* 1. The origin of this software must not be misrepresented; you must not claim * -* that you wrote the original software. If you use this software in a * -* product, an acknowledgment in the product documentation would be * -* appreciated but is not required. * -* * -* 2. Altered source versions must be plainly marked as such, and must not be * -* misrepresented as being the original software. * -* * -* 3. This notice may not be removed or altered from any source distribution. * -* * -********************************************************************************/ - -#ifndef MEMORY_POOL_H -#define MEMORY_POOL_H - -// Libraries -#include "../configuration.h" -#include <cstddef> -#include <cstdlib> -#include <cassert> -#include <new> - -// TODO : Check that casting is done correctly in this class using -// C++ cast operator like reinterpret_cast<>, ... - - -/// ReactPhysics3D namespace -namespace reactphysics3d { - -// Class MemoryPool -/** - * This class represents a memory pool. This memory pool allows us to allocate - * dynamic memory at the beginning of the application in order to - * avoid memory fragmentation and also a large number of allocation - * and deallocation. - */ -template<class T> -class MemoryPool { - - private: - - /// MemoryUnit represents a unit of memory - struct MemoryUnit { - struct MemoryUnit* pNext; // Pointer to the next memory unit - struct MemoryUnit* pPrevious; // Pointer to the previous memory unit - }; - - /// Memory block (that contains several memory units) - struct MemoryBlock { - struct MemoryBlock* pNext; // Pointer to the next memory block - }; - - // -------------------- Constants -------------------- // - - // Number of objects allocated in the first block - static const uint NB_OBJECTS_FIRST_BLOCK; - - // -------------------- Attributes -------------------- // - - /// Pointer to the first allocated memory block - void* mPBlocks; - - /// Pointer to the first allocated memory unit - MemoryUnit* mPAllocatedUnits; - - /// Pointer to the first free memory unit - MemoryUnit* mPFreeUnits; - - /// Current number of objects in the pool - uint mCurrentNbObjects; - - /// Current maximum number of objects that can be allocated in the pool - uint mCapacity; - - /// Number of objects to allocate in the next block - uint mNbObjectsNextBlock; - - // -------------------- Methods -------------------- // - - /// Private copy-constructor - MemoryPool(const MemoryPool& body); - - /// Private assignment operator - MemoryPool& operator=(const MemoryPool& timer); - - /// Allocate more memory (more blocks) when needed - void allocateMemory(); - - public: - - // -------------------- Methods -------------------- // - - /// Constructor - MemoryPool(uint capacity = 0) throw(std::bad_alloc); - - /// Destructor - ~MemoryPool(); - - /// Return the current maximum number of objects allowed in the pool - uint getCapacity() const; - - /// Return the current number of objects in the pool - uint getCurrentNbObjects() const; - - /// Return a pointer to an memory allocated location to store a new object - void* allocateObject(); - - /// Tell the pool that an object doesn't need to be store in the pool anymore - void freeObject(void* pObjectToFree); -}; - -// static member definition -template<class T> const uint MemoryPool<T>::NB_OBJECTS_FIRST_BLOCK = 100; - -// Constructor -/// Allocate a large block of memory in order to contain -/// a given number of object of the template type T -template<class T> -MemoryPool<T>::MemoryPool(uint capacity) throw(std::bad_alloc) - : mCurrentNbObjects(0), mCapacity(capacity) { - mPBlocks = NULL; - mPAllocatedUnits = NULL; - mPFreeUnits = NULL; - mNbObjectsNextBlock = (capacity == 0) ? NB_OBJECTS_FIRST_BLOCK : capacity; - - // Allocate the first memory block if the capacity is - // different from zero - if (capacity) allocateMemory(); -} - -// Destructor -/// Deallocate the blocks of memory that have been allocated previously -template<class T> -MemoryPool<T>::~MemoryPool() { - - // Check if we have a memory leak - assert(mCurrentNbObjects == 0); - - // Release all the allocated memory blocks - MemoryBlock* currentBlock = (MemoryBlock*) mPBlocks; - while(currentBlock) { - MemoryBlock* tempBlock = currentBlock->pNext; - free(currentBlock); - currentBlock = tempBlock; - } -} - -// Return a pointer to a memory allocated location to store a new object. -/// This method only allocates memory if needed and it returns a pointer -/// to a location in an allocated block of memory where a new object can be stored -template<class T> -void* MemoryPool<T>::allocateObject() { - - // If there is not enough allocated memory in the pool - if (mCurrentNbObjects == mCapacity) { - - // Allocate a new memory block - allocateMemory(); - } - - assert(mCurrentNbObjects < mCapacity); - assert(mPFreeUnits != NULL); - - MemoryUnit* currentUnit = mPFreeUnits; - mPFreeUnits = currentUnit->pNext; - if (mPFreeUnits) { - mPFreeUnits->pPrevious = NULL; - } - - currentUnit->pNext = mPAllocatedUnits; - if (mPAllocatedUnits) { - mPAllocatedUnits->pPrevious = currentUnit; - } - mPAllocatedUnits = currentUnit; - - mCurrentNbObjects++; - - // Return a pointer to the allocated memory unit - return (void*)((char*)currentUnit + sizeof(MemoryUnit)); -} - -// Tell the pool that an object does not need to be stored in the pool anymore -/// This method does not deallocate memory because it will be done only at the -/// end but it notifies the memory pool that an object that was stored in the pool -/// does not need to be stored anymore and therefore we can use the corresponding -/// location in the pool for another object -template<class T> -void MemoryPool<T>::freeObject(void* pObjectToFree) { - - // The pointer location must be inside the memory block - //assert(pBlocks<pObjectToFree && pObjectToFree<(void*)((char*)pBlocks + memorySize)); - - MemoryUnit* currentUnit = (MemoryUnit*)((char*)pObjectToFree - sizeof(MemoryUnit)); - mPAllocatedUnits = currentUnit->pNext; - if (mPAllocatedUnits) { - mPAllocatedUnits->pPrevious = NULL; - } - - currentUnit->pNext = mPFreeUnits; - if (mPFreeUnits) { - mPFreeUnits->pPrevious = currentUnit; - } - mPFreeUnits = currentUnit; - - mCurrentNbObjects--; -} - -// Allocate more memory (more blocks) when needed -/// This method is called when there are no -/// free memory units available anymore. Therefore, we need to allocate -/// a new memory block in order to be able to store several new memory units. -template<class T> -void MemoryPool<T>::allocateMemory() { - - // Compute the size of the new - size_t sizeBlock = mNbObjectsNextBlock * (sizeof(MemoryUnit) + sizeof(T)); - - MemoryBlock* tempBlocks = (MemoryBlock*) mPBlocks; - - // Allocate a new memory block - mPBlocks = malloc(sizeBlock); - - // Check that the allocation did not fail - if (mPBlocks == NULL) throw std::bad_alloc(); - - MemoryBlock* block = (MemoryBlock*) mPBlocks; - block->pNext = tempBlocks; - - // For each allocated memory unit in the new block - for (uint i=0; i<mNbObjectsNextBlock; i++) { - - // Get the adress of a memory unit - MemoryUnit* currentUnit = (MemoryUnit*)( (char*)mPBlocks + i * - (sizeof(T) + sizeof(MemoryUnit)) ); - - currentUnit->pPrevious = NULL; - currentUnit->pNext = mPFreeUnits; - - if (mPFreeUnits) { - mPFreeUnits->pPrevious = currentUnit; - } - - mPFreeUnits = currentUnit; - } - - // Update the current capacity of the memory pool - mCapacity += mNbObjectsNextBlock; - - // The next block will be two times the size of the last - // allocated memory block - mNbObjectsNextBlock *= 2; -} - - -// Return the maximum number of objects allowed in the pool -template<class T> -uint MemoryPool<T>::getCapacity() const { - return mCapacity; -} - -// Return the current number of objects in the pool -template<class T> -uint MemoryPool<T>::getCurrentNbObjects() const { - return mCurrentNbObjects; -} - -} - -#endif -