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 );
67 Block( const Block& block );
70 Block& operator=( const Block& block );
76 Impl( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
77 : mFixedSize( fixedSize ),
78 mMemoryBlocks( initialCapacity * mFixedSize ),
79 mMaximumBlockCapacity( maximumBlockCapacity ),
80 mCurrentBlock( &mMemoryBlocks ),
81 mCurrentBlockCapacity( initialCapacity ),
82 mCurrentBlockSize( 0 ),
83 mDeletedObjects( NULL )
85 // We need enough room to store the deleted list in the data
86 DALI_ASSERT_DEBUG( mFixedSize >= sizeof( void* ) );
94 // Clean up memory block linked list (mMemoryBlocks will be auto-destroyed by its destructor)
95 Block* block = mMemoryBlocks.nextBlock;
98 Block* nextBlock = block->nextBlock;
105 * @brief Allocate a new block for allocating memory from
107 void AllocateNewBlock()
109 // Double capacity for the new block
110 SizeType size = mCurrentBlockCapacity * 2;
111 if( size > mMaximumBlockCapacity || size < mCurrentBlockCapacity ) // Check for overflow of size type
113 size = mMaximumBlockCapacity;
116 mCurrentBlockCapacity = size;
119 Block* block = new Block( mCurrentBlockCapacity * mFixedSize );
120 mCurrentBlock->nextBlock = block; // Add to end of linked list
121 mCurrentBlock = block;
123 mCurrentBlockSize = 0;
126 SizeType mFixedSize; ///< The size of each allocation in bytes
128 Block mMemoryBlocks; ///< Linked list of allocated memory blocks
129 SizeType mMaximumBlockCapacity; ///< The maximum allowed capacity of allocations in a new memory block
131 Block* mCurrentBlock; ///< Pointer to the active block
132 SizeType mCurrentBlockCapacity; ///< The maximum number of allocations that can be allocated for the current block
133 SizeType mCurrentBlockSize; ///< The number of allocations allocated to the current block
135 void* mDeletedObjects; ///< Pointer to the head of the list of deleted objects. The addresses are stored in the allocated memory blocks.
138 FixedSizeMemoryPool::FixedSizeMemoryPool( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
140 mImpl = new Impl( fixedSize, initialCapacity, maximumBlockCapacity );
143 FixedSizeMemoryPool::~FixedSizeMemoryPool()
148 void* FixedSizeMemoryPool::Allocate()
150 // First, recycle deleted objects
151 if( mImpl->mDeletedObjects )
153 void* recycled = mImpl->mDeletedObjects;
154 mImpl->mDeletedObjects = *( reinterpret_cast< void** >( mImpl->mDeletedObjects ) ); // Pop head off front of deleted objects list
158 // Check if current block is full
159 if( mImpl->mCurrentBlockSize >= mImpl->mCurrentBlockCapacity )
161 mImpl->AllocateNewBlock();
164 // Placement new the object in block memory
165 unsigned char* objectAddress = static_cast< unsigned char* >( mImpl->mCurrentBlock->blockMemory );
166 objectAddress += mImpl->mCurrentBlockSize * mImpl->mFixedSize;
167 mImpl->mCurrentBlockSize++;
169 return objectAddress;
172 void FixedSizeMemoryPool::Free( void* memory )
174 // Add memory to head of deleted objects list. Store next address in the same memory space as the old object.
175 *( reinterpret_cast< void** >( memory ) ) = mImpl->mDeletedObjects;
176 mImpl->mDeletedObjects = memory;
179 } // namespace Internal