[dali_2.3.28] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / common / memory-pool-object-allocator.h
1 #ifndef DALI_INTERNAL_MEMORY_POOL_OBJECT_ALLOCATOR_H
2 #define DALI_INTERNAL_MEMORY_POOL_OBJECT_ALLOCATOR_H
3
4 /*
5  * Copyright (c) 2024 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <memory> ///< for std::unique_ptr
23
24 // INTERNAL INCLUDES
25 #include <dali/internal/common/dummy-memory-pool.h>
26 #include <dali/internal/common/fixed-size-memory-pool.h>
27
28 namespace Dali
29 {
30 namespace Internal
31 {
32 /**
33  * @brief Helper for allocating/deallocating objects using a memory pool.
34  *
35  * This is a helper class for creating and destroying objects of a single given type.
36  * The type may be a class or POD.
37  *
38  */
39 template<typename T>
40 class MemoryPoolObjectAllocator
41 {
42 public:
43   /**
44    * Constant for use with FixedSizePool. We allow the fixed size pools to grow from 32
45    * to 1M entries per block, but maxing the blocks at 27 allows for many millions of
46    * elements to be quickly indexed using a 32 bit key.
47    */
48   const uint32_t POOL_MAX_BLOCK_COUNT = 27;
49
50   /**
51    * @brief Constructor
52    */
53   MemoryPoolObjectAllocator(bool forceUseMemoryPool = false)
54   : mPool(nullptr),
55     mMemoryPoolEnabled(true)
56   {
57 #if !defined(__LP64__) && defined(LOW_SPEC_MEMORY_MANAGEMENT_ENABLED)
58     if(!forceUseMemoryPool)
59     {
60       mMemoryPoolEnabled = false;
61     }
62 #endif
63     ResetMemoryPool();
64   }
65
66   /**
67    * @brief Destructor
68    */
69   ~MemoryPoolObjectAllocator() = default;
70
71   /**
72    * @brief Allocate a block of memory from the memory pool of the appropriate size to
73    *        store an object of type T. This is usually so the memory can be used in a
74    *        placement new for an object of type T with a constructor that takes multiple
75    *        parameters.
76    *
77    * @return Return the allocated memory block
78    */
79   void* AllocateRaw()
80   {
81     return mPool->Allocate();
82   }
83
84   /**
85    * @brief Thread-safe version of AllocateRaw()
86    *
87    * @return Return the allocated memory block
88    */
89   void* AllocateRawThreadSafe()
90   {
91     return mPool->AllocateThreadSafe();
92   }
93
94   /**
95    * @brief Return the object to the memory pool
96    * Note: This performs a deallocation only, if the object has a destructor and is not
97    * freed from within an overloaded delete operator, Destroy() must be used instead.
98    *
99    * @param object Pointer to the object to delete
100    */
101   void Free(T* object)
102   {
103     mPool->Free(object);
104   }
105
106   /**
107    * @brief Thread-safe version of Free()
108    * Note: This performs a deallocation only, if the object has a destructor and is not
109    * freed from within an overloaded delete operator, DestroyThreadSafe() must be used instead.
110    *
111    * @param object Pointer to the object to delete
112    */
113   void FreeThreadSafe(T* object)
114   {
115     mPool->FreeThreadSafe(object);
116   }
117
118   /**
119    * @brief Return the object to the memory pool after destructing it.
120    * Note: Do not call this from an overloaded delete operator, as this will already have called the objects destructor.
121    *
122    * @param object Pointer to the object to delete
123    */
124   void Destroy(T* object)
125   {
126     object->~T();
127     mPool->Free(object);
128   }
129
130   /**
131    * @brief Thread-safe version of Destroy()
132    * Note: Do not call this from an overloaded delete operator, as this will already have called the objects destructor.
133    *
134    * @param object Pointer to the object to delete
135    */
136   void DestroyThreadSafe(T* object)
137   {
138     object->~T();
139     mPool->FreeThreadSafe(object);
140   }
141
142   /**
143    * @brief Reset the memory pool, unloading all block memory previously allocated
144    */
145   void ResetMemoryPool()
146   {
147     if(DALI_LIKELY(mPool))
148     {
149       mPool->ResetMemoryPool();
150     }
151     else
152     {
153       if(mMemoryPoolEnabled)
154       {
155         mPool.reset(new FixedSizeMemoryPool(TypeSizeWithAlignment<T>::size, 32, 1024 * 1024, POOL_MAX_BLOCK_COUNT));
156       }
157       else
158       {
159         mPool.reset(new DummyMemoryPool(TypeSizeWithAlignment<T>::size));
160       }
161     }
162   }
163
164   /**
165    * Get a pointer to the keyed item.
166    *
167    * Key must be valid.
168    * @param[in] key 32 bit value indexing block/entry
169    * @return ptr to the memory of item, or nullptr if key is invalid
170    *
171    * @note on 32 bit systems, there is zero overhead, key is a raw ptr,
172    * and this method will return it's argument.
173    */
174   T* GetPtrFromKey(MemoryPoolInterface::KeyType key)
175   {
176     return static_cast<T*>(mPool->GetPtrFromKey(key));
177   }
178
179   /**
180    * Get a key to the pointed at item
181    * @param[in] ptr Pointer to an item in the memory pool
182    * @return key of the item, or -1 if not found.
183    *
184    * @note on 32 bit systems, there is zero overhead, key is a raw ptr,
185    * and this method will return it's argument.
186    */
187   MemoryPoolInterface::KeyType GetKeyFromPtr(T* ptr)
188   {
189     return mPool->GetKeyFromPtr(ptr);
190   }
191
192   /**
193    * @brief Get the capacity of the memory pool
194    */
195   uint32_t GetCapacity() const
196   {
197     return mPool->GetCapacity();
198   }
199
200 private:
201   // Undefined
202   MemoryPoolObjectAllocator(const MemoryPoolObjectAllocator& memoryPoolObjectAllocator);
203
204   // Undefined
205   MemoryPoolObjectAllocator& operator=(const MemoryPoolObjectAllocator& memoryPoolObjectAllocator);
206
207 private:
208   std::unique_ptr<MemoryPoolInterface> mPool; ///< Memory pool from which allocations are made
209
210   bool mMemoryPoolEnabled : 1; ///< True if we can use memory pool feature. False otherwise
211 };
212
213 } // namespace Internal
214
215 } // namespace Dali
216
217 #endif // DALI_INTERNAL_MEMORY_POOL_OBJECT_ALLOCATOR_H