Dali 3D User Interface Engine
fixed-size-memory-pool.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17 
18 // CLASS HEADER
20 
21 // INTERNAL HEADERS
24 
25 namespace Dali
26 {
27 
28 namespace Internal
29 {
30 
35 {
41  struct Block
42  {
43  void* blockMemory;
45 
51  Block( SizeType size )
52  : nextBlock( NULL )
53  {
54  blockMemory = ::operator new( size );
55  DALI_ASSERT_ALWAYS( blockMemory && "Out of memory" );
56  }
57 
62  {
63  ::operator delete( blockMemory );
64  }
65 
66  private:
67  // Undefined
68  Block( const Block& block );
69 
70  // Undefined
71  Block& operator=( const Block& block );
72  };
73 
77  Impl( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
78  : mMutex(),
79  mFixedSize( fixedSize ),
80  mMemoryBlocks( initialCapacity * mFixedSize ),
81  mMaximumBlockCapacity( maximumBlockCapacity ),
83  mCurrentBlockCapacity( initialCapacity ),
84  mCurrentBlockSize( 0 ),
85  mDeletedObjects( NULL )
86  {
87  // We need enough room to store the deleted list in the data
88  DALI_ASSERT_DEBUG( mFixedSize >= sizeof( void* ) );
89  }
90 
95  {
96  // Clean up memory block linked list (mMemoryBlocks will be auto-destroyed by its destructor)
97  Block* block = mMemoryBlocks.nextBlock;
98  while( block )
99  {
100  Block* nextBlock = block->nextBlock;
101  delete block;
102  block = nextBlock;
103  }
104  }
105 
110  {
111  // Double capacity for the new block
112  SizeType size = mCurrentBlockCapacity * 2;
113  if( size > mMaximumBlockCapacity || size < mCurrentBlockCapacity ) // Check for overflow of size type
114  {
115  size = mMaximumBlockCapacity;
116  }
117 
118  mCurrentBlockCapacity = size;
119 
120  // Allocate
121  Block* block = new Block( mCurrentBlockCapacity * mFixedSize );
122  mCurrentBlock->nextBlock = block; // Add to end of linked list
123  mCurrentBlock = block;
124 
125  mCurrentBlockSize = 0;
126  }
127 
129 
131 
134 
138 
140 };
141 
142 FixedSizeMemoryPool::FixedSizeMemoryPool( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
143 {
144  mImpl = new Impl( fixedSize, initialCapacity, maximumBlockCapacity );
145 }
146 
148 {
149  delete mImpl;
150 }
151 
153 {
154  // First, recycle deleted objects
155  if( mImpl->mDeletedObjects )
156  {
157  void* recycled = mImpl->mDeletedObjects;
158  mImpl->mDeletedObjects = *( reinterpret_cast< void** >( mImpl->mDeletedObjects ) ); // Pop head off front of deleted objects list
159  return recycled;
160  }
161 
162  // Check if current block is full
164  {
166  }
167 
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;
172 
173  return objectAddress;
174 }
175 
176 void FixedSizeMemoryPool::Free( void* memory )
177 {
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;
181 }
182 
184 {
185  Mutex::ScopedLock lock( mImpl->mMutex );
186  return Allocate();
187 }
188 
190 {
191  Mutex::ScopedLock lock( mImpl->mMutex );
192  Free( memory );
193 }
194 
195 
196 } // namespace Internal
197 
198 } // namespace Dali
Dali Docs Home
Read more about Dali