Add support for passing a single frame allocator from user code

This commit is contained in:
Mkr 2018-09-23 15:30:03 -07:00
parent 78bbb7320d
commit ede45c4188
6 changed files with 76 additions and 33 deletions

View File

@ -149,7 +149,7 @@ SET (REACTPHYSICS3D_HEADERS
"src/mathematics/Ray.h"
"src/memory/MemoryAllocator.h"
"src/memory/PoolAllocator.h"
"src/memory/SingleFrameAllocator.h"
"src/memory/DefaultSingleFrameAllocator.h"
"src/memory/DefaultAllocator.h"
"src/memory/MemoryManager.h"
"src/containers/Stack.h"
@ -227,7 +227,7 @@ SET (REACTPHYSICS3D_SOURCES
"src/mathematics/Vector2.cpp"
"src/mathematics/Vector3.cpp"
"src/memory/PoolAllocator.cpp"
"src/memory/SingleFrameAllocator.cpp"
"src/memory/DefaultSingleFrameAllocator.cpp"
"src/memory/MemoryManager.cpp"
"src/utils/Profiler.cpp"
"src/utils/Logger.cpp"

View File

@ -24,7 +24,7 @@
********************************************************************************/
// Libraries
#include "SingleFrameAllocator.h"
#include "DefaultSingleFrameAllocator.h"
#include "MemoryManager.h"
#include <cstdlib>
#include <cassert>
@ -32,26 +32,27 @@
using namespace reactphysics3d;
// Constructor
SingleFrameAllocator::SingleFrameAllocator()
DefaultSingleFrameAllocator::DefaultSingleFrameAllocator()
: mTotalSizeBytes(INIT_SINGLE_FRAME_ALLOCATOR_NB_BYTES),
mBaseMemoryAllocator(&MemoryManager::getBaseAllocator()),
mCurrentOffset(0), mNbFramesTooMuchAllocated(0), mNeedToAllocatedMore(false) {
// Allocate a whole block of memory at the beginning
mMemoryBufferStart = static_cast<char*>(MemoryManager::getBaseAllocator().allocate(mTotalSizeBytes));
mMemoryBufferStart = static_cast<char*>(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<char*>(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<char*>(MemoryManager::getBaseAllocator().allocate(mTotalSizeBytes));
mMemoryBufferStart = static_cast<char*>(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<char*>(MemoryManager::getBaseAllocator().allocate(mTotalSizeBytes));
mMemoryBufferStart = static_cast<char*>(mBaseMemoryAllocator->allocate(mTotalSizeBytes));
assert(mMemoryBufferStart != nullptr);
mNeedToAllocatedMore = false;

View File

@ -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;
};
}

View File

@ -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

View File

@ -30,5 +30,7 @@ using namespace reactphysics3d;
// Static variables
DefaultAllocator MemoryManager::mDefaultAllocator;
DefaultSingleFrameAllocator MemoryManager::mDefaultSingleFrameAllocator;
MemoryAllocator* MemoryManager::mBaseAllocator = &mDefaultAllocator;
SingleFrameAllocator* MemoryManager::mSingleFrameAllocator = &mDefaultSingleFrameAllocator;

View File

@ -29,7 +29,7 @@
// Libraries
#include "memory/DefaultAllocator.h"
#include "memory/PoolAllocator.h"
#include "memory/SingleFrameAllocator.h"
#include "memory/DefaultSingleFrameAllocator.h"
/// Namespace ReactPhysics3D
namespace reactphysics3d {
@ -45,19 +45,22 @@ class MemoryAllocator;
class MemoryManager {
private:
/// Default malloc/free memory allocator
static DefaultAllocator mDefaultAllocator;
/// Default malloc/free memory allocator
static DefaultSingleFrameAllocator mDefaultSingleFrameAllocator;
/// Pointer to the base memory allocator to use
static MemoryAllocator* mBaseAllocator;
/// Single frame stack allocator
static SingleFrameAllocator* mSingleFrameAllocator;
/// Memory pool allocator
PoolAllocator mPoolAllocator;
/// Single frame stack allocator
SingleFrameAllocator mSingleFrameAllocator;
public:
/// Memory allocation types
@ -87,10 +90,13 @@ class MemoryManager {
/// 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* memoryAllocator);
/// Reset the single frame allocator
void resetFrameAllocator();
};
@ -101,7 +107,7 @@ 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::Frame: return mSingleFrameAllocator->allocate(size);
}
return nullptr;
@ -113,7 +119,7 @@ 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::Frame: mSingleFrameAllocator->release(pointer, size); break;
}
}
@ -124,7 +130,7 @@ inline PoolAllocator& MemoryManager::getPoolAllocator() {
// Return the single frame stack allocator
inline SingleFrameAllocator& MemoryManager::getSingleFrameAllocator() {
return mSingleFrameAllocator;
return *mSingleFrameAllocator;
}
// Return the base memory allocator
@ -137,9 +143,14 @@ inline void MemoryManager::setBaseAllocator(MemoryAllocator* baseAllocator) {
mBaseAllocator = baseAllocator;
}
// Set the base memory allocator
inline void MemoryManager::setSingleFrameAllocator(SingleFrameAllocator* allocator) {
mSingleFrameAllocator = allocator;
}
// Reset the single frame allocator
inline void MemoryManager::resetFrameAllocator() {
mSingleFrameAllocator.reset();
mSingleFrameAllocator->reset();
}
}