Fix VD prevent issues
[platform/core/uifw/dali-core.git] / dali / internal / common / fixed-size-memory-pool.cpp
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
19 #include <dali/internal/common/fixed-size-memory-pool.h>
20
21 // INTERNAL HEADERS
22 #include <dali/public-api/common/dali-common.h>
23
24 namespace Dali
25 {
26
27 namespace Internal
28 {
29
30 /**
31  * @brief Private implementation class
32  */
33 struct FixedSizeMemoryPool::Impl
34 {
35   /**
36    * @brief Struct to represent a block of memory from which allocations can be made.
37    *
38    * The block forms a linked list.
39    */
40   struct Block
41   {
42     void* blockMemory;      ///< The allocated memory from which allocations can be made
43     Block* nextBlock;       ///< The next block in the linked list
44
45     /**
46      * @brief Construct a new block with given size
47      *
48      * @param size The size of the memory block to allocate in bytes. Must be non-zero.
49      */
50     Block( SizeType size )
51     : nextBlock( NULL )
52     {
53       blockMemory = ::operator new( size );
54       DALI_ASSERT_ALWAYS( blockMemory && "Out of memory" );
55     }
56
57     /**
58      * @brief Destructor
59      */
60     ~Block()
61     {
62       ::operator delete( blockMemory );
63     }
64
65   private:
66     // Undefined
67     Block( const Block& block );
68
69     // Undefined
70     Block& operator=( const Block& block );
71   };
72
73   /**
74    * @brief Constructor
75    */
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 )
84   {
85     // We need enough room to store the deleted list in the data
86     DALI_ASSERT_DEBUG( mFixedSize >= sizeof( void* ) );
87   }
88
89   /**
90    * @brief Destructor
91    */
92   ~Impl()
93   {
94     // Clean up memory block linked list (mMemoryBlocks will be auto-destroyed by its destructor)
95     Block* block = mMemoryBlocks.nextBlock;
96     while( block )
97     {
98       Block* nextBlock = block->nextBlock;
99       delete block;
100       block = nextBlock;
101     }
102   }
103
104   /**
105    * @brief Allocate a new block for allocating memory from
106    */
107   void AllocateNewBlock()
108   {
109     // Double capacity for the new block
110     SizeType size = mCurrentBlockCapacity * 2;
111     if( size > mMaximumBlockCapacity || size < mCurrentBlockCapacity )    // Check for overflow of size type
112     {
113       size = mMaximumBlockCapacity;
114     }
115
116     mCurrentBlockCapacity = size;
117
118     // Allocate
119     Block* block = new Block( mCurrentBlockCapacity * mFixedSize );
120     mCurrentBlock->nextBlock = block;       // Add to end of linked list
121     mCurrentBlock = block;
122
123     mCurrentBlockSize = 0;
124   }
125
126   SizeType mFixedSize;                ///< The size of each allocation in bytes
127
128   Block mMemoryBlocks;                ///< Linked list of allocated memory blocks
129   SizeType mMaximumBlockCapacity;     ///< The maximum allowed capacity of allocations in a new memory block
130
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
134
135   void* mDeletedObjects;              ///< Pointer to the head of the list of deleted objects. The addresses are stored in the allocated memory blocks.
136 };
137
138 FixedSizeMemoryPool::FixedSizeMemoryPool( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
139 {
140   mImpl = new Impl( fixedSize, initialCapacity, maximumBlockCapacity );
141 }
142
143 FixedSizeMemoryPool::~FixedSizeMemoryPool()
144 {
145   delete mImpl;
146 }
147
148 void* FixedSizeMemoryPool::Allocate()
149 {
150   // First, recycle deleted objects
151   if( mImpl->mDeletedObjects )
152   {
153     void* recycled = mImpl->mDeletedObjects;
154     mImpl->mDeletedObjects = *( reinterpret_cast< void** >( mImpl->mDeletedObjects ) );  // Pop head off front of deleted objects list
155     return recycled;
156   }
157
158   // Check if current block is full
159   if( mImpl->mCurrentBlockSize >= mImpl->mCurrentBlockCapacity )
160   {
161     mImpl->AllocateNewBlock();
162   }
163
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++;
168
169   return objectAddress;
170 }
171
172 void FixedSizeMemoryPool::Free( void* memory )
173 {
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;
177 }
178
179 } // namespace Internal
180
181 } // namespace Dali