use modern construct 'nullptr' instead of 'NULL' or '0'
[platform/core/uifw/dali-core.git] / dali / internal / common / fixed-size-memory-pool.cpp
index 8b69193..29723b1 100644 (file)
@@ -19,6 +19,7 @@
 #include <dali/internal/common/fixed-size-memory-pool.h>
 
 // INTERNAL HEADERS
+#include <dali/devel-api/threading/mutex.h>
 #include <dali/public-api/common/dali-common.h>
 
 namespace Dali
@@ -41,14 +42,19 @@ struct FixedSizeMemoryPool::Impl
   {
     void* blockMemory;      ///< The allocated memory from which allocations can be made
     Block* nextBlock;       ///< The next block in the linked list
-
+#ifdef DEBUG_ENABLED
+    SizeType mBlockSize; ///< Size of the block in bytes
+#endif
     /**
      * @brief Construct a new block with given size
      *
      * @param size The size of the memory block to allocate in bytes. Must be non-zero.
      */
     Block( SizeType size )
-    : nextBlock( NULL )
+    : nextBlock( nullptr )
+#ifdef DEBUG_ENABLED
+      ,mBlockSize( size )
+#endif
     {
       blockMemory = ::operator new( size );
       DALI_ASSERT_ALWAYS( blockMemory && "Out of memory" );
@@ -74,13 +80,14 @@ struct FixedSizeMemoryPool::Impl
    * @brief Constructor
    */
   Impl( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
-  :  mFixedSize( fixedSize ),
+  :  mMutex(),
+     mFixedSize( fixedSize ),
      mMemoryBlocks( initialCapacity * mFixedSize ),
      mMaximumBlockCapacity( maximumBlockCapacity ),
      mCurrentBlock( &mMemoryBlocks ),
      mCurrentBlockCapacity( initialCapacity ),
      mCurrentBlockSize( 0 ),
-     mDeletedObjects( NULL )
+     mDeletedObjects( nullptr )
   {
     // We need enough room to store the deleted list in the data
     DALI_ASSERT_DEBUG( mFixedSize >= sizeof( void* ) );
@@ -122,6 +129,33 @@ struct FixedSizeMemoryPool::Impl
 
     mCurrentBlockSize = 0;
   }
+#ifdef DEBUG_ENABLED
+
+  /**
+   * @brief check the memory being free'd exists inside the memory pool
+   * @param[in] memory address of object to remove
+   */
+  void CheckMemoryIsInsidePool( const void* const memory )
+  {
+    bool inRange = false;
+    const Block* block = &mMemoryBlocks;
+
+    while( block )
+    {
+      const void* const endOfBlock = reinterpret_cast<char *>( block->blockMemory )+ block->mBlockSize;
+
+      if( ( memory >= block->blockMemory ) && ( memory < (endOfBlock) ) )
+      {
+        inRange = true;
+        break;
+      }
+      block = block->nextBlock;
+    }
+    DALI_ASSERT_DEBUG( inRange && "Freeing memory that does not exist in memory pool" );
+  }
+#endif
+
+  Mutex mMutex;                       ///< Mutex for thread-safe allocation and deallocation
 
   SizeType mFixedSize;                ///< The size of each allocation in bytes
 
@@ -162,7 +196,7 @@ void* FixedSizeMemoryPool::Allocate()
   }
 
   // Placement new the object in block memory
-  unsigned char* objectAddress = static_cast< unsigned char* >( mImpl->mCurrentBlock->blockMemory );
+  uint8_t* objectAddress = static_cast< uint8_t* >( mImpl->mCurrentBlock->blockMemory );
   objectAddress += mImpl->mCurrentBlockSize * mImpl->mFixedSize;
   mImpl->mCurrentBlockSize++;
 
@@ -171,11 +205,28 @@ void* FixedSizeMemoryPool::Allocate()
 
 void FixedSizeMemoryPool::Free( void* memory )
 {
+#ifdef DEBUG_ENABLED
+  mImpl->CheckMemoryIsInsidePool( memory );
+#endif
+
   // Add memory to head of deleted objects list. Store next address in the same memory space as the old object.
   *( reinterpret_cast< void** >( memory ) ) = mImpl->mDeletedObjects;
   mImpl->mDeletedObjects = memory;
 }
 
+void* FixedSizeMemoryPool::AllocateThreadSafe()
+{
+  Mutex::ScopedLock lock( mImpl->mMutex );
+  return Allocate();
+}
+
+void FixedSizeMemoryPool::FreeThreadSafe( void* memory )
+{
+  Mutex::ScopedLock lock( mImpl->mMutex );
+  Free( memory );
+}
+
+
 } // namespace Internal
 
 } // namespace Dali