Finish the implementation of the memory allocator
This commit is contained in:
parent
f784dfb320
commit
e03888ea25
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ class GJKAlgorithm : public NarrowPhaseAlgorithm {
|
|||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
GJKAlgorithm(MemoryPool<ContactInfo>& memoryPoolContactInfos);
|
||||
GJKAlgorithm(MemoryAllocator& memoryAllocator);
|
||||
|
||||
/// Destructor
|
||||
~GJKAlgorithm();
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ class SphereVsSphereAlgorithm : public NarrowPhaseAlgorithm {
|
|||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
SphereVsSphereAlgorithm(MemoryPool<ContactInfo>& memoryPoolContactInfos);
|
||||
SphereVsSphereAlgorithm(MemoryAllocator& memoryAllocator);
|
||||
|
||||
/// Destructor
|
||||
virtual ~SphereVsSphereAlgorithm();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ class OverlappingPair {
|
|||
|
||||
/// Constructor
|
||||
OverlappingPair(CollisionBody* body1, CollisionBody* body2,
|
||||
MemoryPool<ContactPoint>& memoryPoolContacts);
|
||||
MemoryAllocator& memoryAllocator);
|
||||
|
||||
/// Destructor
|
||||
~OverlappingPair();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user