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/devel-api/threading/mutex.h>
23 #include <dali/public-api/common/dali-common.h>
32 * @brief Private implementation class
34 struct FixedSizeMemoryPool::Impl
37 * @brief Struct to represent a block of memory from which allocations can be made.
39 * The block forms a linked list.
43 void* blockMemory; ///< The allocated memory from which allocations can be made
44 Block* nextBlock; ///< The next block in the linked list
47 * @brief Construct a new block with given size
49 * @param size The size of the memory block to allocate in bytes. Must be non-zero.
51 Block( SizeType size )
54 blockMemory = ::operator new( size );
55 DALI_ASSERT_ALWAYS( blockMemory && "Out of memory" );
63 ::operator delete( blockMemory );
68 Block( const Block& block );
71 Block& operator=( const Block& block );
77 Impl( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
79 mFixedSize( fixedSize ),
80 mMemoryBlocks( initialCapacity * mFixedSize ),
81 mMaximumBlockCapacity( maximumBlockCapacity ),
82 mCurrentBlock( &mMemoryBlocks ),
83 mCurrentBlockCapacity( initialCapacity ),
84 mCurrentBlockSize( 0 ),
85 mDeletedObjects( NULL )
87 // We need enough room to store the deleted list in the data
88 DALI_ASSERT_DEBUG( mFixedSize >= sizeof( void* ) );
96 // Clean up memory block linked list (mMemoryBlocks will be auto-destroyed by its destructor)
97 Block* block = mMemoryBlocks.nextBlock;
100 Block* nextBlock = block->nextBlock;
107 * @brief Allocate a new block for allocating memory from
109 void AllocateNewBlock()
111 // Double capacity for the new block
112 SizeType size = mCurrentBlockCapacity * 2;
113 if( size > mMaximumBlockCapacity || size < mCurrentBlockCapacity ) // Check for overflow of size type
115 size = mMaximumBlockCapacity;
118 mCurrentBlockCapacity = size;
121 Block* block = new Block( mCurrentBlockCapacity * mFixedSize );
122 mCurrentBlock->nextBlock = block; // Add to end of linked list
123 mCurrentBlock = block;
125 mCurrentBlockSize = 0;
128 Mutex mMutex; ///< Mutex for thread-safe allocation and deallocation
130 SizeType mFixedSize; ///< The size of each allocation in bytes
132 Block mMemoryBlocks; ///< Linked list of allocated memory blocks
133 SizeType mMaximumBlockCapacity; ///< The maximum allowed capacity of allocations in a new memory block
135 Block* mCurrentBlock; ///< Pointer to the active block
136 SizeType mCurrentBlockCapacity; ///< The maximum number of allocations that can be allocated for the current block
137 SizeType mCurrentBlockSize; ///< The number of allocations allocated to the current block
139 void* mDeletedObjects; ///< Pointer to the head of the list of deleted objects. The addresses are stored in the allocated memory blocks.
142 FixedSizeMemoryPool::FixedSizeMemoryPool( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
144 mImpl = new Impl( fixedSize, initialCapacity, maximumBlockCapacity );
147 FixedSizeMemoryPool::~FixedSizeMemoryPool()
152 void* FixedSizeMemoryPool::Allocate()
154 // First, recycle deleted objects
155 if( mImpl->mDeletedObjects )
157 void* recycled = mImpl->mDeletedObjects;
158 mImpl->mDeletedObjects = *( reinterpret_cast< void** >( mImpl->mDeletedObjects ) ); // Pop head off front of deleted objects list
162 // Check if current block is full
163 if( mImpl->mCurrentBlockSize >= mImpl->mCurrentBlockCapacity )
165 mImpl->AllocateNewBlock();
168 // Placement new the object in block memory
169 unsigned char* objectAddress = static_cast< unsigned char* >( mImpl->mCurrentBlock->blockMemory );
170 objectAddress += mImpl->mCurrentBlockSize * mImpl->mFixedSize;
171 mImpl->mCurrentBlockSize++;
173 return objectAddress;
176 void FixedSizeMemoryPool::Free( void* memory )
178 // Add memory to head of deleted objects list. Store next address in the same memory space as the old object.
179 *( reinterpret_cast< void** >( memory ) ) = mImpl->mDeletedObjects;
180 mImpl->mDeletedObjects = memory;
183 void* FixedSizeMemoryPool::AllocateThreadSafe()
185 Mutex::ScopedLock lock( mImpl->mMutex );
189 void FixedSizeMemoryPool::FreeThreadSafe( void* memory )
191 Mutex::ScopedLock lock( mImpl->mMutex );
196 } // namespace Internal