Make memory allocators thread safe

This commit is contained in:
Daniel Chappuis 2020-05-25 10:10:40 +02:00
parent cfdab52573
commit 23041d474b
7 changed files with 41 additions and 8 deletions

View File

@ -52,12 +52,12 @@ class DefaultAllocator : public MemoryAllocator {
/// allocated memory. /// allocated memory.
virtual void* allocate(size_t size) override { virtual void* allocate(size_t size) override {
return malloc(size); return std::malloc(size);
} }
/// Release previously allocated memory. /// Release previously allocated memory.
virtual void release(void* pointer, size_t size) override { virtual void release(void* pointer, size_t size) override {
free(pointer); std::free(pointer);
} }
}; };

View File

@ -30,6 +30,7 @@
#include <reactphysics3d/configuration.h> #include <reactphysics3d/configuration.h>
#include <reactphysics3d/memory/MemoryAllocator.h> #include <reactphysics3d/memory/MemoryAllocator.h>
#include <cassert> #include <cassert>
#include <mutex>
#include <reactphysics3d/containers/Map.h> #include <reactphysics3d/containers/Map.h>
/// ReactPhysics3D namespace /// ReactPhysics3D namespace
@ -88,6 +89,9 @@ class HeapAllocator : public MemoryAllocator {
// -------------------- Attributes -------------------- // // -------------------- Attributes -------------------- //
// Mutex
std::mutex mMutex;
/// Base memory allocator /// Base memory allocator
MemoryAllocator& mBaseAllocator; MemoryAllocator& mBaseAllocator;
@ -117,6 +121,9 @@ class HeapAllocator : public MemoryAllocator {
// Merge two contiguous memory units that are not allocated. // Merge two contiguous memory units that are not allocated.
void mergeUnits(MemoryUnitHeader* unit1, MemoryUnitHeader* unit2); void mergeUnits(MemoryUnitHeader* unit1, MemoryUnitHeader* unit2);
/// Reserve more memory for the allocator
void reserve(size_t sizeToAllocate);
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
@ -128,7 +135,7 @@ class HeapAllocator : public MemoryAllocator {
virtual ~HeapAllocator() override; virtual ~HeapAllocator() override;
/// Assignment operator /// Assignment operator
HeapAllocator& operator=(HeapAllocator& allocator) = default; HeapAllocator& operator=(HeapAllocator& allocator) = delete;
/// Allocate memory of a given size (in bytes) and return a pointer to the /// Allocate memory of a given size (in bytes) and return a pointer to the
/// allocated memory. /// allocated memory.
@ -136,9 +143,6 @@ class HeapAllocator : public MemoryAllocator {
/// Release previously allocated memory. /// Release previously allocated memory.
virtual void release(void* pointer, size_t size) override; virtual void release(void* pointer, size_t size) override;
/// Reserve more memory for the allocator
void reserve(size_t sizeToAllocate);
}; };
} }

View File

@ -29,6 +29,7 @@
// Libraries // Libraries
#include <reactphysics3d/configuration.h> #include <reactphysics3d/configuration.h>
#include <reactphysics3d/memory/MemoryAllocator.h> #include <reactphysics3d/memory/MemoryAllocator.h>
#include <mutex>
/// ReactPhysics3D namespace /// ReactPhysics3D namespace
namespace reactphysics3d { namespace reactphysics3d {
@ -101,6 +102,9 @@ class PoolAllocator : public MemoryAllocator {
/// True if the mMapSizeToHeapIndex array has already been initialized /// True if the mMapSizeToHeapIndex array has already been initialized
static bool isMapSizeToHeadIndexInitialized; static bool isMapSizeToHeadIndexInitialized;
/// Mutex
std::mutex mMutex;
/// Base memory allocator /// Base memory allocator
MemoryAllocator& mBaseAllocator; MemoryAllocator& mBaseAllocator;
@ -135,7 +139,7 @@ class PoolAllocator : public MemoryAllocator {
virtual ~PoolAllocator() override; virtual ~PoolAllocator() override;
/// Assignment operator /// Assignment operator
PoolAllocator& operator=(PoolAllocator& allocator) = default; PoolAllocator& operator=(PoolAllocator& allocator) = delete;
/// Allocate memory of a given size (in bytes) and return a pointer to the /// Allocate memory of a given size (in bytes) and return a pointer to the
/// allocated memory. /// allocated memory.

View File

@ -29,6 +29,7 @@
// Libraries // Libraries
#include <reactphysics3d/memory/MemoryAllocator.h> #include <reactphysics3d/memory/MemoryAllocator.h>
#include <reactphysics3d/configuration.h> #include <reactphysics3d/configuration.h>
#include <mutex>
/// ReactPhysics3D namespace /// ReactPhysics3D namespace
namespace reactphysics3d { namespace reactphysics3d {
@ -53,6 +54,9 @@ class SingleFrameAllocator : public MemoryAllocator {
// -------------------- Attributes -------------------- // // -------------------- Attributes -------------------- //
/// Mutex
std::mutex mMutex;
/// Reference to the base memory allocator /// Reference to the base memory allocator
MemoryAllocator& mBaseAllocator; MemoryAllocator& mBaseAllocator;
@ -83,7 +87,7 @@ class SingleFrameAllocator : public MemoryAllocator {
virtual ~SingleFrameAllocator() override; virtual ~SingleFrameAllocator() override;
/// Assignment operator /// Assignment operator
SingleFrameAllocator& operator=(SingleFrameAllocator& allocator) = default; SingleFrameAllocator& operator=(SingleFrameAllocator& allocator) = delete;
/// Allocate memory of a given size (in bytes) /// Allocate memory of a given size (in bytes)
virtual void* allocate(size_t size) override; virtual void* allocate(size_t size) override;

View File

@ -107,6 +107,9 @@ void HeapAllocator::splitMemoryUnit(MemoryUnitHeader* unit, size_t size) {
// allocated memory. // allocated memory.
void* HeapAllocator::allocate(size_t size) { void* HeapAllocator::allocate(size_t size) {
// Lock the method with a mutex
std::lock_guard<std::mutex> lock(mMutex);
assert(size > 0); assert(size > 0);
// We cannot allocate zero bytes // We cannot allocate zero bytes
@ -176,6 +179,9 @@ void* HeapAllocator::allocate(size_t size) {
// Release previously allocated memory. // Release previously allocated memory.
void HeapAllocator::release(void* pointer, size_t size) { void HeapAllocator::release(void* pointer, size_t size) {
// Lock the method with a mutex
std::lock_guard<std::mutex> lock(mMutex);
assert(size > 0); assert(size > 0);
// Cannot release a 0-byte allocated memory // Cannot release a 0-byte allocated memory

View File

@ -100,6 +100,9 @@ PoolAllocator::~PoolAllocator() {
// allocated memory. // allocated memory.
void* PoolAllocator::allocate(size_t size) { void* PoolAllocator::allocate(size_t size) {
// Lock the method with a mutex
std::lock_guard<std::mutex> lock(mMutex);
assert(size > 0); assert(size > 0);
// We cannot allocate zero bytes // We cannot allocate zero bytes
@ -175,6 +178,9 @@ void* PoolAllocator::allocate(size_t size) {
// Release previously allocated memory. // Release previously allocated memory.
void PoolAllocator::release(void* pointer, size_t size) { void PoolAllocator::release(void* pointer, size_t size) {
// Lock the method with a mutex
std::lock_guard<std::mutex> lock(mMutex);
assert(size > 0); assert(size > 0);
// Cannot release a 0-byte allocated memory // Cannot release a 0-byte allocated memory

View File

@ -53,6 +53,9 @@ SingleFrameAllocator::~SingleFrameAllocator() {
// allocated memory. // allocated memory.
void* SingleFrameAllocator::allocate(size_t size) { void* SingleFrameAllocator::allocate(size_t size) {
// Lock the method with a mutex
std::lock_guard<std::mutex> lock(mMutex);
// Check that there is enough remaining memory in the buffer // Check that there is enough remaining memory in the buffer
if (mCurrentOffset + size > mTotalSizeBytes) { if (mCurrentOffset + size > mTotalSizeBytes) {
@ -76,6 +79,9 @@ void* SingleFrameAllocator::allocate(size_t size) {
// Release previously allocated memory. // Release previously allocated memory.
void SingleFrameAllocator::release(void* pointer, size_t size) { void SingleFrameAllocator::release(void* pointer, size_t size) {
// Lock the method with a mutex
std::lock_guard<std::mutex> lock(mMutex);
// If allocated memory is not within the single frame allocation range // If allocated memory is not within the single frame allocation range
char* p = static_cast<char*>(pointer); char* p = static_cast<char*>(pointer);
if (p < mMemoryBufferStart || p > mMemoryBufferStart + mTotalSizeBytes) { if (p < mMemoryBufferStart || p > mMemoryBufferStart + mTotalSizeBytes) {
@ -88,6 +94,9 @@ void SingleFrameAllocator::release(void* pointer, size_t size) {
// Reset the marker of the current allocated memory // Reset the marker of the current allocated memory
void SingleFrameAllocator::reset() { void SingleFrameAllocator::reset() {
// Lock the method with a mutex
std::lock_guard<std::mutex> lock(mMutex);
// If too much memory is allocated // If too much memory is allocated
if (mCurrentOffset < mTotalSizeBytes / 2) { if (mCurrentOffset < mTotalSizeBytes / 2) {