2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/common/fixed-size-memory-pool.h>
22 #include <dali/public-api/common/dali-common.h>
31 * @brief Private implementation class
33 struct FixedSizeMemoryPool::Impl
36 * @brief Struct to represent a block of memory from which allocations can be made.
38 * The block forms a linked list.
42 void* blockMemory; ///< The allocated memory from which allocations can be made
43 Block* nextBlock; ///< The next block in the linked list
46 * @brief Construct a new block with given size
48 * @param size The size of the memory block to allocate in bytes. Must be non-zero.
50 Block( SizeType size )
53 blockMemory = ::operator new( size );
54 DALI_ASSERT_ALWAYS( blockMemory && "Out of memory" );
62 ::operator delete( blockMemory );
69 Impl( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
70 : mFixedSize( fixedSize ),
71 mMemoryBlocks( initialCapacity * mFixedSize ),
72 mMaximumBlockCapacity( maximumBlockCapacity ),
73 mCurrentBlock( &mMemoryBlocks ),
74 mCurrentBlockCapacity( initialCapacity ),
75 mCurrentBlockSize( 0 ),
76 mDeletedObjects( NULL )
78 // We need enough room to store the deleted list in the data
79 DALI_ASSERT_DEBUG( mFixedSize >= sizeof( void* ) );
87 // Clean up memory block linked list (mMemoryBlocks will be auto-destroyed by its destructor)
88 Block* block = mMemoryBlocks.nextBlock;
91 Block* nextBlock = block->nextBlock;
98 * @brief Allocate a new block for allocating memory from
100 void AllocateNewBlock()
102 // Double capacity for the new block
103 SizeType size = mCurrentBlockCapacity * 2;
104 if( size > mMaximumBlockCapacity || size < mCurrentBlockCapacity ) // Check for overflow of size type
106 size = mMaximumBlockCapacity;
109 mCurrentBlockCapacity = size;
112 Block* block = new Block( mCurrentBlockCapacity * mFixedSize );
113 mCurrentBlock->nextBlock = block; // Add to end of linked list
114 mCurrentBlock = block;
116 mCurrentBlockSize = 0;
119 SizeType mFixedSize; ///< The size of each allocation in bytes
121 Block mMemoryBlocks; ///< Linked list of allocated memory blocks
122 SizeType mMaximumBlockCapacity; ///< The maximum allowed capacity of allocations in a new memory block
124 Block* mCurrentBlock; ///< Pointer to the active block
125 SizeType mCurrentBlockCapacity; ///< The maximum number of allocations that can be allocated for the current block
126 SizeType mCurrentBlockSize; ///< The number of allocations allocated to the current block
128 void* mDeletedObjects; ///< Pointer to the head of the list of deleted objects. The addresses are stored in the allocated memory blocks.
131 FixedSizeMemoryPool::FixedSizeMemoryPool( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
133 mImpl = new Impl( fixedSize, initialCapacity, maximumBlockCapacity );
136 FixedSizeMemoryPool::~FixedSizeMemoryPool()
141 void* FixedSizeMemoryPool::Allocate()
143 // First, recycle deleted objects
144 if( mImpl->mDeletedObjects )
146 void* recycled = mImpl->mDeletedObjects;
147 mImpl->mDeletedObjects = *( reinterpret_cast< void** >( mImpl->mDeletedObjects ) ); // Pop head off front of deleted objects list
151 // Check if current block is full
152 if( mImpl->mCurrentBlockSize >= mImpl->mCurrentBlockCapacity )
154 mImpl->AllocateNewBlock();
157 // Placement new the object in block memory
158 unsigned char* objectAddress = static_cast< unsigned char* >( mImpl->mCurrentBlock->blockMemory );
159 objectAddress += mImpl->mCurrentBlockSize * mImpl->mFixedSize;
160 mImpl->mCurrentBlockSize++;
162 return objectAddress;
165 void FixedSizeMemoryPool::Free( void* memory )
167 // Add memory to head of deleted objects list. Store next address in the same memory space as the old object.
168 *( reinterpret_cast< void** >( memory ) ) = mImpl->mDeletedObjects;
169 mImpl->mDeletedObjects = memory;
172 } // namespace Internal