X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fcommon%2Ffixed-size-memory-pool.cpp;h=44e0fd35fabe39bc0156de91a64739226eafaf9c;hb=e4d22de85c81987aa749fb21dca87e88ed170509;hp=f225a8d883f0ad5f0283d9ae569e07e1fe317a87;hpb=c8e0d2807617b0ba441ae67e735512bf6f3c1c68;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 f225a8d..44e0fd3 100644 --- a/dali/internal/common/fixed-size-memory-pool.cpp +++ b/dali/internal/common/fixed-size-memory-pool.cpp @@ -21,6 +21,8 @@ // INTERNAL HEADERS #include #include +#include +#include namespace Dali { @@ -40,20 +42,22 @@ 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 +#if defined(__LP64__) + KeyType mIndexOffset; ///< The Offset of this block's index #endif + SizeType mBlockSize; ///< Size of the block in bytes + /** * @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(nullptr) -#ifdef DEBUG_ENABLED - , - mBlockSize(size) + : nextBlock(nullptr), +#if defined(__LP64__) + mIndexOffset(0), #endif + mBlockSize(size) { blockMemory = ::operator new(size); DALI_ASSERT_ALWAYS(blockMemory && "Out of memory"); @@ -78,7 +82,7 @@ struct FixedSizeMemoryPool::Impl /** * @brief Constructor */ - Impl(SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity) + Impl(SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity, SizeType maximumBlockCount) : mMutex(), mFixedSize(fixedSize), mMemoryBlocks(initialCapacity * mFixedSize), @@ -86,10 +90,26 @@ struct FixedSizeMemoryPool::Impl mCurrentBlock(&mMemoryBlocks), mCurrentBlockCapacity(initialCapacity), mCurrentBlockSize(0), + mMaximumBlockCount(maximumBlockCount), mDeletedObjects(nullptr) { // We need enough room to store the deleted list in the data DALI_ASSERT_DEBUG(mFixedSize >= sizeof(void*)); + +#if defined(__LP64__) + if(mMaximumBlockCount < 0xffffffff) + { + // Only use mBlocks for key/ptr conversion with max number of blocks + mBlocks.reserve(32); + mBlocks.push_back(&mMemoryBlocks); + + // Compute masks and shifts + int bitCount = (logf(mMaximumBlockCount) / logf(2.0f)) + 1; + mBlockShift = 32 - bitCount; + mBlockIdMask = ((0x01 << bitCount) - 1) << mBlockShift; + mIndexMask = ~mBlockIdMask; + } +#endif } /** @@ -122,9 +142,46 @@ 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); + +#if defined(__LP64__) + if(mBlockShift) // Key contains block id & index within block + { + // Add to main list of blocks + mBlocks.push_back(block); +#endif + mCurrentBlock->nextBlock = block; // Add end of linked list + mCurrentBlock = block; +#if defined(__LP64__) + } + else + { + // Heuristic optimization. Make bigger block positioned at front, instead of header. + // (Since change the Block value might be heavy) + if(mCurrentBlock == &mMemoryBlocks) + { + block->mIndexOffset = mMemoryBlocks.mBlockSize / mFixedSize; + + // Add to end of linked list. + // Now mCurrentBlock is next block of header. + mCurrentBlock->nextBlock = block; + mCurrentBlock = block; + } + else + { + block->mIndexOffset = mCurrentBlock->mIndexOffset + (mCurrentBlock->mBlockSize / mFixedSize); + + // Add new block as next of header. + mMemoryBlocks.nextBlock = block; + + // Make previous mCurrentBlock as next of new block. + block->nextBlock = mCurrentBlock; + + // Keep mCurrentBlock is next block of mMemoryBlocks. + mCurrentBlock = block; + } + } +#endif mCurrentBlockSize = 0; } @@ -161,16 +218,31 @@ struct FixedSizeMemoryPool::Impl Block mMemoryBlocks; ///< Linked list of allocated memory blocks SizeType mMaximumBlockCapacity; ///< The maximum allowed capacity of allocations in a new memory block +#if defined(__LP64__) + std::vector mBlocks; ///< Address of each allocated block +#endif + 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 mMaximumBlockCount{0xffffffff}; ///< Maximum number of blocks (or unlimited) +#if defined(__LP64__) + SizeType mBlockShift{0x0}; ///< number of bits to shift block id in key + SizeType mBlockIdMask{0x0}; ///< mask for key conversion + SizeType mIndexMask{0xffffffff}; ///< mask for key conversion +#endif + 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, + SizeType maximumBlockCount) { - mImpl = new Impl(fixedSize, initialCapacity, maximumBlockCapacity); + mImpl = new Impl(fixedSize, initialCapacity, maximumBlockCapacity, maximumBlockCount); } FixedSizeMemoryPool::~FixedSizeMemoryPool() @@ -231,6 +303,98 @@ void FixedSizeMemoryPool::FreeThreadSafe(void* memory) } } +void* FixedSizeMemoryPool::GetPtrFromKey(FixedSizeMemoryPool::KeyType key) +{ +#if defined(__LP64__) + uint32_t blockId{0u}; + uint32_t index = key & mImpl->mIndexMask; + + if(DALI_LIKELY(mImpl->mBlockShift)) // Key contains block id & index within block + { + blockId = (key & mImpl->mBlockIdMask) >> mImpl->mBlockShift; + if(blockId < mImpl->mBlocks.size()) + { + return static_cast(mImpl->mBlocks[blockId]->blockMemory) + mImpl->mFixedSize * index; + } + return nullptr; + } + else + { + // Treat as having no block id, and search for Nth item + Impl::Block* block = &mImpl->mMemoryBlocks; + while(block != nullptr) + { + const uint32_t indexOffset = block->mIndexOffset; + const SizeType numberOfItems = (block->mBlockSize) / mImpl->mFixedSize; + if(indexOffset <= index && index < indexOffset + numberOfItems) + { + return static_cast(block->blockMemory) + mImpl->mFixedSize * (index - indexOffset); + } + block = block->nextBlock; + } + } + return nullptr; +#else + // Treat ptrs as keys + return static_cast(key); +#endif +} + +FixedSizeMemoryPool::KeyType FixedSizeMemoryPool::GetKeyFromPtr(void* ptr) +{ +#if defined(__LP64__) + uint32_t blockId = 0; + uint32_t index = 0; + bool found = false; + + // If block count is limited, the bit shift is non-zero. + if(DALI_LIKELY(mImpl->mBlockShift)) + { + // Iterate backward so we can search at bigger blocks first. + blockId = mImpl->mBlocks.size(); + for(auto iter = mImpl->mBlocks.rbegin(), iterEnd = mImpl->mBlocks.rend(); iter != iterEnd; ++iter) + { + --blockId; + auto* block = *iter; + + const void* const endOfBlock = reinterpret_cast(block->blockMemory) + block->mBlockSize; + + if(block->blockMemory <= ptr && ptr < endOfBlock) + { + index = (static_cast(ptr) - static_cast(block->blockMemory)) / mImpl->mFixedSize; + found = true; + break; + } + } + } + else + { + // Block count is unlimited, key is item count. But, potentially have to iterate through many blocks. + Impl::Block* block = &mImpl->mMemoryBlocks; + while(block != nullptr && !found) + { + const void* const endOfBlock = reinterpret_cast(block->blockMemory) + block->mBlockSize; + + if(block->blockMemory <= ptr && ptr < endOfBlock) + { + index = block->mIndexOffset + (static_cast(ptr) - static_cast(block->blockMemory)) / mImpl->mFixedSize; + found = true; + break; + } + block = block->nextBlock; + } + } + if(found) + { + return blockId << mImpl->mBlockShift | (index & mImpl->mIndexMask); + } + + return -1; +#else + return static_cast(ptr); +#endif +} + uint32_t FixedSizeMemoryPool::GetCapacity() const { // Ignores deleted objects list, just returns currently allocated size