X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=dali%2Finternal%2Fcommon%2Ffixed-size-memory-pool.cpp;h=f225a8d883f0ad5f0283d9ae569e07e1fe317a87;hb=c8e0d2807617b0ba441ae67e735512bf6f3c1c68;hp=c2594aa0aad0d2913a011feb0ab01e2257bd62e8;hpb=6a9a86815730fc72cdb815b9f577e50f4f3cb49d;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/common/fixed-size-memory-pool.cpp b/dali/internal/common/fixed-size-memory-pool.cpp index c2594aa..f225a8d 100644 --- a/dali/internal/common/fixed-size-memory-pool.cpp +++ b/dali/internal/common/fixed-size-memory-pool.cpp @@ -19,14 +19,13 @@ #include // INTERNAL HEADERS -#include +#include +#include namespace Dali { - namespace Internal { - /** * @brief Private implementation class */ @@ -39,19 +38,25 @@ struct FixedSizeMemoryPool::Impl */ struct Block { - void* blockMemory; ///< The allocated memory from which allocations can be made - Block* nextBlock; ///< The next block in the linked list - + 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 ) + Block(SizeType size) + : nextBlock(nullptr) +#ifdef DEBUG_ENABLED + , + mBlockSize(size) +#endif { - blockMemory = ::operator new( size ); - DALI_ASSERT_ALWAYS( blockMemory && "Out of memory" ); + blockMemory = ::operator new(size); + DALI_ASSERT_ALWAYS(blockMemory && "Out of memory"); } /** @@ -59,24 +64,32 @@ struct FixedSizeMemoryPool::Impl */ ~Block() { - ::operator delete( blockMemory ); + ::operator delete(blockMemory); } + + private: + // Undefined + Block(const Block& block); + + // Undefined + Block& operator=(const Block& block); }; /** * @brief Constructor */ - Impl( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity ) - : mFixedSize( fixedSize ), - mMemoryBlocks( initialCapacity * mFixedSize ), - mMaximumBlockCapacity( maximumBlockCapacity ), - mCurrentBlock( &mMemoryBlocks ), - mCurrentBlockCapacity( initialCapacity ), - mCurrentBlockSize( 0 ), - mDeletedObjects( NULL ) + Impl(SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity) + : mMutex(), + mFixedSize(fixedSize), + mMemoryBlocks(initialCapacity * mFixedSize), + mMaximumBlockCapacity(maximumBlockCapacity), + mCurrentBlock(&mMemoryBlocks), + mCurrentBlockCapacity(initialCapacity), + mCurrentBlockSize(0), + mDeletedObjects(nullptr) { // We need enough room to store the deleted list in the data - DALI_ASSERT_DEBUG( mFixedSize >= sizeof( void* ) ); + DALI_ASSERT_DEBUG(mFixedSize >= sizeof(void*)); } /** @@ -86,7 +99,7 @@ struct FixedSizeMemoryPool::Impl { // Clean up memory block linked list (mMemoryBlocks will be auto-destroyed by its destructor) Block* block = mMemoryBlocks.nextBlock; - while( block ) + while(block) { Block* nextBlock = block->nextBlock; delete block; @@ -101,7 +114,7 @@ struct FixedSizeMemoryPool::Impl { // Double capacity for the new block SizeType size = mCurrentBlockCapacity * 2; - if( size > mMaximumBlockCapacity || size < mCurrentBlockCapacity ) // Check for overflow of size type + if(size > mMaximumBlockCapacity || size < mCurrentBlockCapacity) // Check for overflow of size type { size = mMaximumBlockCapacity; } @@ -109,28 +122,55 @@ struct FixedSizeMemoryPool::Impl mCurrentBlockCapacity = size; // Allocate - Block* block = new Block( mCurrentBlockCapacity * mFixedSize ); - mCurrentBlock->nextBlock = block; // Add to end of linked list - mCurrentBlock = block; + Block* block = new Block(mCurrentBlockCapacity * mFixedSize); + mCurrentBlock->nextBlock = block; // Add to end of linked list + mCurrentBlock = block; mCurrentBlockSize = 0; } +#ifdef DEBUG_ENABLED - SizeType mFixedSize; ///< The size of each allocation in bytes + /** + * @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; - Block mMemoryBlocks; ///< Linked list of allocated memory blocks - SizeType mMaximumBlockCapacity; ///< The maximum allowed capacity of allocations in a new memory block + while(block) + { + const void* const endOfBlock = reinterpret_cast(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 - Block* mCurrentBlock; ///< Pointer to the active block - SizeType mCurrentBlockCapacity; ///< The maximum number of allocations that can be allocated for the current block - SizeType mCurrentBlockSize; ///< The number of allocations allocated to the current block + SizeType mFixedSize; ///< The size of each allocation in bytes - void* mDeletedObjects; ///< Pointer to the head of the list of deleted objects. The addresses are stored in the allocated memory blocks. + Block mMemoryBlocks; ///< Linked list of allocated memory blocks + SizeType mMaximumBlockCapacity; ///< The maximum allowed capacity of allocations in a new memory block + + Block* mCurrentBlock; ///< Pointer to the active block + SizeType mCurrentBlockCapacity; ///< The maximum number of allocations that can be allocated for the current block + SizeType mCurrentBlockSize; ///< The number of allocations allocated to the current block + + void* mDeletedObjects; ///< Pointer to the head of the list of deleted objects. The addresses are stored in the allocated memory blocks. }; -FixedSizeMemoryPool::FixedSizeMemoryPool( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity ) +FixedSizeMemoryPool::FixedSizeMemoryPool(SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity) { - mImpl = new Impl( fixedSize, initialCapacity, maximumBlockCapacity ); + mImpl = new Impl(fixedSize, initialCapacity, maximumBlockCapacity); } FixedSizeMemoryPool::~FixedSizeMemoryPool() @@ -141,32 +181,70 @@ FixedSizeMemoryPool::~FixedSizeMemoryPool() void* FixedSizeMemoryPool::Allocate() { // First, recycle deleted objects - if( mImpl->mDeletedObjects ) + if(mImpl->mDeletedObjects) { - void* recycled = mImpl->mDeletedObjects; - mImpl->mDeletedObjects = *( reinterpret_cast< void** >( mImpl->mDeletedObjects ) ); // Pop head off front of deleted objects list + void* recycled = mImpl->mDeletedObjects; + mImpl->mDeletedObjects = *(reinterpret_cast(mImpl->mDeletedObjects)); // Pop head off front of deleted objects list return recycled; } // Check if current block is full - if( mImpl->mCurrentBlockSize >= mImpl->mCurrentBlockCapacity ) + if(mImpl->mCurrentBlockSize >= mImpl->mCurrentBlockCapacity) { mImpl->AllocateNewBlock(); } // Placement new the object in block memory - unsigned char* objectAddress = static_cast< unsigned char* >( mImpl->mCurrentBlock->blockMemory ); + uint8_t* objectAddress = static_cast(mImpl->mCurrentBlock->blockMemory); objectAddress += mImpl->mCurrentBlockSize * mImpl->mFixedSize; mImpl->mCurrentBlockSize++; return objectAddress; } -void FixedSizeMemoryPool::Free( void* memory ) +void FixedSizeMemoryPool::Free(void* memory) +{ + if(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(memory)) = mImpl->mDeletedObjects; + mImpl->mDeletedObjects = memory; + } +} + +void* FixedSizeMemoryPool::AllocateThreadSafe() +{ + Mutex::ScopedLock lock(mImpl->mMutex); + return Allocate(); +} + +void FixedSizeMemoryPool::FreeThreadSafe(void* memory) { - // 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; + if(memory) + { + Mutex::ScopedLock lock(mImpl->mMutex); + Free(memory); + } +} + +uint32_t FixedSizeMemoryPool::GetCapacity() const +{ + // Ignores deleted objects list, just returns currently allocated size + uint32_t totalAllocation = 0; +#ifdef DEBUG_ENABLED + Mutex::ScopedLock lock(mImpl->mMutex); + Impl::Block* block = &mImpl->mMemoryBlocks; + while(block) + { + totalAllocation += block->mBlockSize; + block = block->nextBlock; + } +#endif + return totalAllocation; } } // namespace Internal