From 23041d474b8ab936f4d99a2fa015139761070eb8 Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Mon, 25 May 2020 10:10:40 +0200 Subject: [PATCH] Make memory allocators thread safe --- include/reactphysics3d/memory/DefaultAllocator.h | 4 ++-- include/reactphysics3d/memory/HeapAllocator.h | 12 ++++++++---- include/reactphysics3d/memory/PoolAllocator.h | 6 +++++- include/reactphysics3d/memory/SingleFrameAllocator.h | 6 +++++- src/memory/HeapAllocator.cpp | 6 ++++++ src/memory/PoolAllocator.cpp | 6 ++++++ src/memory/SingleFrameAllocator.cpp | 9 +++++++++ 7 files changed, 41 insertions(+), 8 deletions(-) diff --git a/include/reactphysics3d/memory/DefaultAllocator.h b/include/reactphysics3d/memory/DefaultAllocator.h index c061961a..fd89d346 100644 --- a/include/reactphysics3d/memory/DefaultAllocator.h +++ b/include/reactphysics3d/memory/DefaultAllocator.h @@ -52,12 +52,12 @@ class DefaultAllocator : public MemoryAllocator { /// allocated memory. virtual void* allocate(size_t size) override { - return malloc(size); + return std::malloc(size); } /// Release previously allocated memory. virtual void release(void* pointer, size_t size) override { - free(pointer); + std::free(pointer); } }; diff --git a/include/reactphysics3d/memory/HeapAllocator.h b/include/reactphysics3d/memory/HeapAllocator.h index 64c192ab..ef7dcc44 100644 --- a/include/reactphysics3d/memory/HeapAllocator.h +++ b/include/reactphysics3d/memory/HeapAllocator.h @@ -30,6 +30,7 @@ #include #include #include +#include #include /// ReactPhysics3D namespace @@ -88,6 +89,9 @@ class HeapAllocator : public MemoryAllocator { // -------------------- Attributes -------------------- // + // Mutex + std::mutex mMutex; + /// Base memory allocator MemoryAllocator& mBaseAllocator; @@ -117,6 +121,9 @@ class HeapAllocator : public MemoryAllocator { // Merge two contiguous memory units that are not allocated. void mergeUnits(MemoryUnitHeader* unit1, MemoryUnitHeader* unit2); + /// Reserve more memory for the allocator + void reserve(size_t sizeToAllocate); + public : // -------------------- Methods -------------------- // @@ -128,7 +135,7 @@ class HeapAllocator : public MemoryAllocator { virtual ~HeapAllocator() override; /// 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 /// allocated memory. @@ -136,9 +143,6 @@ class HeapAllocator : public MemoryAllocator { /// Release previously allocated memory. virtual void release(void* pointer, size_t size) override; - - /// Reserve more memory for the allocator - void reserve(size_t sizeToAllocate); }; } diff --git a/include/reactphysics3d/memory/PoolAllocator.h b/include/reactphysics3d/memory/PoolAllocator.h index 8b3f799f..03b325ed 100644 --- a/include/reactphysics3d/memory/PoolAllocator.h +++ b/include/reactphysics3d/memory/PoolAllocator.h @@ -29,6 +29,7 @@ // Libraries #include #include +#include /// ReactPhysics3D namespace namespace reactphysics3d { @@ -101,6 +102,9 @@ class PoolAllocator : public MemoryAllocator { /// True if the mMapSizeToHeapIndex array has already been initialized static bool isMapSizeToHeadIndexInitialized; + /// Mutex + std::mutex mMutex; + /// Base memory allocator MemoryAllocator& mBaseAllocator; @@ -135,7 +139,7 @@ class PoolAllocator : public MemoryAllocator { virtual ~PoolAllocator() override; /// 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 /// allocated memory. diff --git a/include/reactphysics3d/memory/SingleFrameAllocator.h b/include/reactphysics3d/memory/SingleFrameAllocator.h index cf4d5a49..85f20a04 100644 --- a/include/reactphysics3d/memory/SingleFrameAllocator.h +++ b/include/reactphysics3d/memory/SingleFrameAllocator.h @@ -29,6 +29,7 @@ // Libraries #include #include +#include /// ReactPhysics3D namespace namespace reactphysics3d { @@ -53,6 +54,9 @@ class SingleFrameAllocator : public MemoryAllocator { // -------------------- Attributes -------------------- // + /// Mutex + std::mutex mMutex; + /// Reference to the base memory allocator MemoryAllocator& mBaseAllocator; @@ -83,7 +87,7 @@ class SingleFrameAllocator : public MemoryAllocator { virtual ~SingleFrameAllocator() override; /// Assignment operator - SingleFrameAllocator& operator=(SingleFrameAllocator& allocator) = default; + SingleFrameAllocator& operator=(SingleFrameAllocator& allocator) = delete; /// Allocate memory of a given size (in bytes) virtual void* allocate(size_t size) override; diff --git a/src/memory/HeapAllocator.cpp b/src/memory/HeapAllocator.cpp index 5d9b95d0..59a8fe3c 100644 --- a/src/memory/HeapAllocator.cpp +++ b/src/memory/HeapAllocator.cpp @@ -107,6 +107,9 @@ void HeapAllocator::splitMemoryUnit(MemoryUnitHeader* unit, size_t size) { // allocated memory. void* HeapAllocator::allocate(size_t size) { + // Lock the method with a mutex + std::lock_guard lock(mMutex); + assert(size > 0); // We cannot allocate zero bytes @@ -176,6 +179,9 @@ void* HeapAllocator::allocate(size_t size) { // Release previously allocated memory. void HeapAllocator::release(void* pointer, size_t size) { + // Lock the method with a mutex + std::lock_guard lock(mMutex); + assert(size > 0); // Cannot release a 0-byte allocated memory diff --git a/src/memory/PoolAllocator.cpp b/src/memory/PoolAllocator.cpp index 4a406dd4..41a025c6 100644 --- a/src/memory/PoolAllocator.cpp +++ b/src/memory/PoolAllocator.cpp @@ -100,6 +100,9 @@ PoolAllocator::~PoolAllocator() { // allocated memory. void* PoolAllocator::allocate(size_t size) { + // Lock the method with a mutex + std::lock_guard lock(mMutex); + assert(size > 0); // We cannot allocate zero bytes @@ -175,6 +178,9 @@ void* PoolAllocator::allocate(size_t size) { // Release previously allocated memory. void PoolAllocator::release(void* pointer, size_t size) { + // Lock the method with a mutex + std::lock_guard lock(mMutex); + assert(size > 0); // Cannot release a 0-byte allocated memory diff --git a/src/memory/SingleFrameAllocator.cpp b/src/memory/SingleFrameAllocator.cpp index 63be5a24..e92c45cb 100644 --- a/src/memory/SingleFrameAllocator.cpp +++ b/src/memory/SingleFrameAllocator.cpp @@ -53,6 +53,9 @@ SingleFrameAllocator::~SingleFrameAllocator() { // allocated memory. void* SingleFrameAllocator::allocate(size_t size) { + // Lock the method with a mutex + std::lock_guard lock(mMutex); + // Check that there is enough remaining memory in the buffer if (mCurrentOffset + size > mTotalSizeBytes) { @@ -76,6 +79,9 @@ void* SingleFrameAllocator::allocate(size_t size) { // Release previously allocated memory. void SingleFrameAllocator::release(void* pointer, size_t size) { + // Lock the method with a mutex + std::lock_guard lock(mMutex); + // If allocated memory is not within the single frame allocation range char* p = static_cast(pointer); 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 void SingleFrameAllocator::reset() { + // Lock the method with a mutex + std::lock_guard lock(mMutex); + // If too much memory is allocated if (mCurrentOffset < mTotalSizeBytes / 2) {