+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<uint8_t*>(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<uint8_t*>(block->blockMemory) + mImpl->mFixedSize * (index - indexOffset);
+ }
+ block = block->nextBlock;
+ }
+ }
+ return nullptr;
+#else
+ // Treat ptrs as keys
+ return static_cast<void*>(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<char*>(block->blockMemory) + block->mBlockSize;
+
+ if(block->blockMemory <= ptr && ptr < endOfBlock)
+ {
+ index = (static_cast<uint8_t*>(ptr) - static_cast<uint8_t*>(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<char*>(block->blockMemory) + block->mBlockSize;
+
+ if(block->blockMemory <= ptr && ptr < endOfBlock)
+ {
+ index = block->mIndexOffset + (static_cast<uint8_t*>(ptr) - static_cast<uint8_t*>(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<FixedSizeMemoryPool::KeyType>(ptr);
+#endif
+}
+