29 #include <unordered_map> 31 #include <unordered_set> 33 #include "MemoryAllocator.h" 34 #include "STDAllocator.h" 41 inline void FillWithDebugPattern(
void *ptr, Uint8 Pattern,
size_t NumBytes)
43 memset(ptr, Pattern, NumBytes);
46 #define FillWithDebugPattern(...) 57 virtual void*
Allocate(
size_t Size,
const Char* dbgDescription,
const char* dbgFileName,
const Int32 dbgLineNumber)
override final;
60 virtual void Free(
void *Ptr)
override final;
75 static constexpr Uint8 NewPageMemPattern = 0xAA;
76 static constexpr Uint8 AllocatedBlockMemPattern = 0xAB;
77 static constexpr Uint8 DeallocatedBlockMemPattern = 0xDE;
78 static constexpr Uint8 InitializedBlockMemPattern = 0xCF;
81 m_pOwnerAllocator(&OwnerAllocator),
82 m_NumFreeBlocks(OwnerAllocator.m_NumBlocksInPage),
83 m_NumInitializedBlocks(0)
85 auto PageSize = OwnerAllocator.m_BlockSize * OwnerAllocator.m_NumBlocksInPage;
86 m_pPageStart =
reinterpret_cast<Uint8*
>(
87 OwnerAllocator.m_RawMemoryAllocator.Allocate(PageSize,
"FixedBlockMemoryAllocator page", __FILE__, __LINE__)
89 m_pNextFreeBlock = m_pPageStart;
90 FillWithDebugPattern(m_pPageStart, NewPageMemPattern, PageSize);
93 MemoryPage(MemoryPage&& Page) :
94 m_NumFreeBlocks(Page.m_NumFreeBlocks),
95 m_NumInitializedBlocks(Page.m_NumInitializedBlocks),
96 m_pPageStart(Page.m_pPageStart),
97 m_pNextFreeBlock(Page.m_pNextFreeBlock),
98 m_pOwnerAllocator(Page.m_pOwnerAllocator)
100 Page.m_NumFreeBlocks = 0;
101 Page.m_NumInitializedBlocks = 0;
102 Page.m_pPageStart =
nullptr;
103 Page.m_pNextFreeBlock =
nullptr;
104 Page.m_pOwnerAllocator =
nullptr;
109 if(m_pOwnerAllocator)
110 m_pOwnerAllocator->m_RawMemoryAllocator.Free(m_pPageStart);
113 void* GetBlockStartAddress(Uint32 BlockIndex)
const 115 VERIFY_EXPR(m_pOwnerAllocator !=
nullptr);
116 VERIFY(BlockIndex >= 0 && BlockIndex < m_pOwnerAllocator->m_NumBlocksInPage,
"Invalid block index" );
117 return reinterpret_cast<Uint8*
>(m_pPageStart) + BlockIndex * m_pOwnerAllocator->m_BlockSize;
121 void dbgVerifyAddress(
const void* pBlockAddr)
const 123 size_t Delta =
reinterpret_cast<const Uint8*
>(pBlockAddr) - reinterpret_cast<Uint8*>(m_pPageStart);
124 VERIFY(Delta % m_pOwnerAllocator->m_BlockSize == 0,
"Invalid address");
125 Uint32 BlockIndex =
static_cast<Uint32
>(Delta / m_pOwnerAllocator->m_BlockSize);
126 VERIFY(BlockIndex >= 0 && BlockIndex < m_pOwnerAllocator->m_NumBlocksInPage,
"Invalid block index" );
129 #define dbgVerifyAddress(...) 134 VERIFY_EXPR(m_pOwnerAllocator !=
nullptr);
136 if (m_NumFreeBlocks == 0)
138 VERIFY_EXPR(m_NumInitializedBlocks == m_pOwnerAllocator->m_NumBlocksInPage);
143 if (m_NumInitializedBlocks < m_pOwnerAllocator->m_NumBlocksInPage)
161 auto *pUninitializedBlock = GetBlockStartAddress(m_NumInitializedBlocks);
162 FillWithDebugPattern(pUninitializedBlock, InitializedBlockMemPattern, m_pOwnerAllocator->m_BlockSize);
163 void** ppNextBlock =
reinterpret_cast<void**
>( pUninitializedBlock );
164 ++m_NumInitializedBlocks;
165 if( m_NumInitializedBlocks < m_pOwnerAllocator->m_NumBlocksInPage )
166 *ppNextBlock = GetBlockStartAddress(m_NumInitializedBlocks);
168 *ppNextBlock =
nullptr;
171 void* res = m_pNextFreeBlock;
172 dbgVerifyAddress(res);
174 m_pNextFreeBlock = *
reinterpret_cast<void**
>(m_pNextFreeBlock);
176 if(m_NumFreeBlocks != 0)
177 dbgVerifyAddress(m_pNextFreeBlock);
179 VERIFY_EXPR(m_pNextFreeBlock ==
nullptr);
181 FillWithDebugPattern(res, AllocatedBlockMemPattern, m_pOwnerAllocator->m_BlockSize);
185 void DeAllocate(
void* p)
187 VERIFY_EXPR(m_pOwnerAllocator !=
nullptr);
190 FillWithDebugPattern(p, DeallocatedBlockMemPattern, m_pOwnerAllocator->m_BlockSize);
192 *
reinterpret_cast<void**
>(p) = m_pNextFreeBlock;
193 m_pNextFreeBlock = p;
197 bool HasSpace()
const{
return m_NumFreeBlocks>0;}
198 bool HasAllocations()
const{
return m_NumFreeBlocks<m_NumInitializedBlocks;}
201 MemoryPage(
const MemoryPage&)=
delete;
202 MemoryPage& operator = (
const MemoryPage)=
delete;
203 MemoryPage& operator = (MemoryPage&&)=
delete;
205 Uint32 m_NumFreeBlocks = 0;
206 Uint32 m_NumInitializedBlocks = 0;
207 void* m_pPageStart =
nullptr;
208 void* m_pNextFreeBlock =
nullptr;
212 std::vector<MemoryPage, STDAllocatorRawMem<MemoryPage> > m_PagePool;
213 std::unordered_set<size_t, std::hash<size_t>, std::equal_to<size_t>, STDAllocatorRawMem<size_t> > m_AvailablePages;
214 typedef std::pair<void* const, size_t> AddrToPageIdMapElem;
215 std::unordered_map<void*, size_t, std::hash<void*>, std::equal_to<void*>, STDAllocatorRawMem<AddrToPageIdMapElem> > m_AddrToPageId;
219 IMemoryAllocator &m_RawMemoryAllocator;
221 Uint32 m_NumBlocksInPage;
226 template<
typename ObjectType>
233 if(m_bPoolInitialized && m_pRawAllocator != &Allocator)
235 LOG_WARNING_MESSAGE(
"Setting pool raw allocator after the pool has been initialized has no effect");
238 m_pRawAllocator = &Allocator;
240 static void SetPageSize(Uint32 NumAllocationsInPage)
243 if(m_bPoolInitialized && m_NumAllocationsInPage != NumAllocationsInPage)
245 LOG_WARNING_MESSAGE(
"Setting pool page size after the pool has been initialized has no effect");
248 m_NumAllocationsInPage = NumAllocationsInPage;
250 static ObjectPool& GetPool()
252 static ObjectPool ThePool;
254 m_bPoolInitialized =
true;
259 template<
typename ... CtorArgTypes>
260 ObjectType* NewObject(
const Char* dbgDescription,
const char* dbgFileName,
const Int32 dbgLineNumber, CtorArgTypes&& ... CtorArgs)
262 void *pRawMem = m_FixedBlockAlloctor.Allocate(
sizeof(ObjectType), dbgDescription, dbgFileName, dbgLineNumber);
265 return new(pRawMem) ObjectType(std::forward<CtorArgTypes>(CtorArgs)...);
269 m_FixedBlockAlloctor.Free(pRawMem);
274 void Destroy(ObjectType* pObj)
279 m_FixedBlockAlloctor.Free(pObj);
284 static Uint32 m_NumAllocationsInPage;
285 static IMemoryAllocator *m_pRawAllocator;
288 m_FixedBlockAlloctor(m_pRawAllocator ? *m_pRawAllocator :
GetRawAllocator(), sizeof(ObjectType), m_NumAllocationsInPage)
291 static bool m_bPoolInitialized;
293 FixedBlockMemoryAllocator m_FixedBlockAlloctor;
295 template<
typename ObjectType>
296 Uint32 ObjectPool<ObjectType>::m_NumAllocationsInPage = 64;
298 template<
typename ObjectType>
299 IMemoryAllocator* ObjectPool<ObjectType>::m_pRawAllocator =
nullptr;
302 template<
typename ObjectType>
303 bool ObjectPool<ObjectType>::m_bPoolInitialized =
false;
306 #define SET_POOL_RAW_ALLOCATOR(ObjectType, Allocator)ObjectPool<ObjectType>::SetRawAllocator(Allocator) 307 #define SET_POOL_PAGE_SIZE(ObjectType, NumAllocationsInPage)ObjectPool<ObjectType>::SetPageSize(NumAllocationsInPage) 308 #define NEW_POOL_OBJECT(ObjectType, Desc, ...)ObjectPool<ObjectType>::GetPool().NewObject(Desc, __FILE__, __LINE__, ##__VA_ARGS__) 309 #define DESTROY_POOL_OBJECT(pObject)ObjectPool< std::remove_reference<decltype(*pObject)>::type >::GetPool().Destroy(pObject) Namespace for the OpenGL implementation of the graphics engine.
Definition: BufferD3D11Impl.h:34
virtual void * Allocate(size_t Size, const Char *dbgDescription, const char *dbgFileName, const Int32 dbgLineNumber) override final
Allocates block of memory.
Definition: FixedBlockMemoryAllocator.cpp:64
IMemoryAllocator & GetRawAllocator()
Returns raw memory allocator.
Definition: EngineMemory.cpp:46
void SetRawAllocator(IMemoryAllocator *pRawAllocator)
Sets raw memory allocator. This function must be called before any memory allocation/deallocation fun...
Definition: EngineMemory.cpp:36
Memory allocator that allocates memory in a fixed-size chunks.
Definition: FixedBlockMemoryAllocator.h:50
virtual void Free(void *Ptr) override final
Releases memory.
Definition: FixedBlockMemoryAllocator.cpp:91