Version

menu_open
Wwise SDK 2023.1.9
AkDynaBlkPool.h
Go to the documentation of this file.
1 /*******************************************************************************
2 The content of this file includes portions of the AUDIOKINETIC Wwise Technology
3 released in source code form as part of the SDK installer package.
4 
5 Commercial License Usage
6 
7 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
8 may use this file in accordance with the end user license agreement provided
9 with the software or, alternatively, in accordance with the terms contained in a
10 written agreement between you and Audiokinetic Inc.
11 
12 Apache License Usage
13 
14 Alternatively, this file may be used under the Apache License, Version 2.0 (the
15 "Apache License"); you may not use this file except in compliance with the
16 Apache License. You may obtain a copy of the Apache License at
17 http://www.apache.org/licenses/LICENSE-2.0.
18 
19 Unless required by applicable law or agreed to in writing, software distributed
20 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
21 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
22 the specific language governing permissions and limitations under the License.
23 
24  Copyright (c) 2024 Audiokinetic Inc.
25 *******************************************************************************/
26 
27 #ifndef _AKBLOCKPOOL_H
28 #define _AKBLOCKPOOL_H
29 
33 
34 //
35 // AkDynaBlkPool - A dynamic block pool allocator which will grow (and shrink) in size in contiguous chunks of 'uPoolChunkSize' objects.
36 // - Fragmentation in the pool will prevent it from shrinking, but in many use cases this is acceptable.
37 //
38 
39 #ifdef _DEBUG
40 //#define AK_DYNA_BLK_STATS
41 #define AK_DYNA_BLK_SCRUB_MEM
42 #endif
43 
44 #ifdef AK_DYNA_BLK_STATS
45 #define STATS_ALLOC() Stats_Alloc()
46 #define STATS_NEWCHUNK() Stats_NewChunk()
47 #define STATS_FREE() Stats_Free()
48 #define STATS_DELCHUNK() Stats_DelChunk()
49 #else
50 #define STATS_ALLOC()
51 #define STATS_NEWCHUNK()
52 #define STATS_FREE()
53 #define STATS_DELCHUNK()
54 #endif
55 
56 #ifdef AK_DYNA_BLK_SCRUB_MEM
57 #define SCRUB_NEW_CHUNK() memset(&memory, 0xCC, sizeof(T)*uPoolChunkSize)
58 #define SCRUB_NEW_ALLOC(pItem) memset(pItem, 0xAA, sizeof(T))
59 #define SCRUB_FREE_BLOCK(pObj) memset(pObj, 0xDD, sizeof(T))
60 #else
61 #define SCRUB_NEW_CHUNK()
62 #define SCRUB_NEW_ALLOC(pItem)
63 #define SCRUB_FREE_BLOCK(pObj)
64 #endif
65 
66 template < typename T, AkUInt32 uPoolChunkSize, class TAlloc = ArrayPoolDefault>
67 class AkDynaBlkPool: public TAlloc
68 {
69  enum { kChunkMemoryBytes = sizeof(T)*uPoolChunkSize };
70 
71  struct FreeBlock
72  {
73  FreeBlock* pNextItem;
74  char padding[ sizeof(T) - sizeof(FreeBlock*) ];
75  };
77 
78  struct PoolChunk
79  {
80  PoolChunk() : pNextLightItem(NULL)
81  {
83  for( AkUInt32 i=0; i<uPoolChunkSize; ++i )
84  {
85  FreeBlock* pBlk = reinterpret_cast<FreeBlock*>( &memory ) + i;
86  freeList.AddFirst(pBlk);
87  }
88  }
89 
90  inline bool BelongsTo( FreeBlock* pMem ) const { return (AkUInt8*)pMem >= memory && (AkUInt8*)pMem < (memory+kChunkMemoryBytes); }
91  inline bool AllFree() const { return freeList.Length() == uPoolChunkSize; }
92  inline bool AllAllocd() const { return freeList.IsEmpty(); }
93 
94  AkUInt8 memory[ kChunkMemoryBytes ];
95  PoolChunk* pNextLightItem;
96  tFreeList freeList;
97  };
99 
100 public:
101 
102  T* New()
103  {
104  T* ptr = Alloc();
105  if (ptr) AkPlacementNew(ptr) T;
106  return ptr;
107  }
108 
109  template<typename A1>
110  T* New(A1 a1)
111  {
112  T* ptr = Alloc();
113  if (ptr) AkPlacementNew(ptr) T(a1);
114  return ptr;
115  }
116 
117  template<typename A1, typename A2>
118  T* New(A1 a1, A2 a2)
119  {
120  T* ptr = Alloc();
121  if (ptr) AkPlacementNew(ptr) T(a1, a2);
122  return ptr;
123  }
124 
125  template<typename A1, typename A2, typename A3>
126  T* New(A1 a1, A2 a2, A3 a3)
127  {
128  T* ptr = Alloc();
129  if (ptr) AkPlacementNew(ptr) T(a1, a2, a3);
130  return ptr;
131  }
132 
133  template<typename A1, typename A2, typename A3, typename A4>
134  T* New(A1 a1, A2 a2, A3 a3, A4 a4)
135  {
136  T* ptr = Alloc();
137  if (ptr) AkPlacementNew(ptr) T(a1,a2,a3,a4);
138  return ptr;
139  }
140 
141  void Delete(T* ptr)
142  {
143  ptr->~T();
144  Free(ptr);
145  }
146 
148  {
149  m_chunkList.Transfer(in_src.m_chunkList);
150 
151 #ifdef AK_DYNA_BLK_STATS
152  uPeakUsedBytes = in_src.uPeakUsedBytes;
153  uPeakAllocdBytes = in_src.uPeakAllocdBytes;
154  uCurrentAllocdBytes = in_src.uCurrentAllocdBytes;
155  uCurrentUsedBytes = in_src.uCurrentUsedBytes;
156 
157  in_src.uPeakUsedBytes = 0;
158  in_src.uPeakAllocdBytes = 0;
159  in_src.uCurrentAllocdBytes = 0;
160  in_src.uCurrentUsedBytes = 0;
161 #endif
162  }
163 
164 private:
165  T* Alloc()
166  {
167  FreeBlock* pItem = NULL;
168  PoolChunk* pChunk = NULL;
169 
170  pChunk = m_chunkList.First();
171  while (pChunk != NULL && pChunk->AllAllocd())
172  pChunk = pChunk->pNextLightItem;
173 
174  if (pChunk == NULL)
175  {
176  pChunk = (PoolChunk *) TAlloc::Alloc( sizeof( PoolChunk ) );
177  AkPlacementNew(pChunk) PoolChunk();
178  STATS_NEWCHUNK();
179  if (pChunk != NULL)
180  m_chunkList.AddFirst(pChunk);
181  }
182 
183  if (pChunk != NULL)
184  {
185  pItem = pChunk->freeList.First();
186  AKASSERT(pItem != NULL);
187  pChunk->freeList.RemoveFirst();
188  SCRUB_NEW_ALLOC(pItem);
189  STATS_ALLOC();
190  }
191 
192  return reinterpret_cast<T*>(pItem);
193  }
194 
195  void Free( T* pObj )
196  {
197  SCRUB_FREE_BLOCK((void*)pObj);
198 
199  FreeBlock* pItem = reinterpret_cast<FreeBlock*>(pObj);
200 
201  PoolChunk* pPrevChunk = NULL;
202  PoolChunk* pChunk = m_chunkList.First();
203  while (pChunk != NULL && !pChunk->BelongsTo(pItem))
204  {
205  pPrevChunk = pChunk;
206  pChunk = pChunk->pNextLightItem;
207  }
208 
209  AKASSERT(pChunk != NULL);
210  pChunk->freeList.AddFirst(pItem);
211  STATS_FREE();
212 
213  if (pChunk->AllFree())
214  {
215  m_chunkList.RemoveItem(pChunk, pPrevChunk);
216  pChunk->~PoolChunk();
217  TAlloc::Free( pChunk );
218  STATS_DELCHUNK();
219  }
220  }
221 
222  tChunkList m_chunkList;
223 
224 #ifdef AK_DYNA_BLK_STATS
225  void Stats_Alloc()
226  {
227  uCurrentUsedBytes += sizeof(T);
228  uPeakUsedBytes = AkMax(uCurrentUsedBytes, uPeakUsedBytes);
229  }
230  void Stats_NewChunk()
231  {
232  uCurrentAllocdBytes += sizeof(PoolChunk);
233  uPeakAllocdBytes = AkMax(uCurrentAllocdBytes, uPeakAllocdBytes);
234  }
235  void Stats_Free()
236  {
237  uCurrentUsedBytes -= sizeof(T);
238  }
239  void Stats_DelChunk()
240  {
241  uCurrentAllocdBytes -= sizeof(PoolChunk);
242  }
243 public:
244  AkUInt32 uPeakUsedBytes;
245  AkUInt32 uPeakAllocdBytes;
246  AkUInt32 uCurrentAllocdBytes;
247  AkUInt32 uCurrentUsedBytes;
248 #endif
249 };
250 
251 
252 #endif
AkForceInline T * First()
Get first element.
Definition: AkListBare.h:390
#define SCRUB_FREE_BLOCK(pObj)
Definition: AkDynaBlkPool.h:63
#define STATS_DELCHUNK()
Definition: AkDynaBlkPool.h:53
#define AkMax(x1, x2)
AKSOUNDENGINE_API void Free(AkMemPoolId in_poolId, void *in_pMemAddress)
#define SCRUB_NEW_CHUNK()
Definition: AkDynaBlkPool.h:61
uint8_t AkUInt8
Unsigned 8-bit integer.
#define STATS_ALLOC()
Definition: AkDynaBlkPool.h:50
#define NULL
Definition: AkTypes.h:46
void AddFirst(T *in_pItem)
Add element at the beginning of list.
Definition: AkListBare.h:308
#define STATS_NEWCHUNK()
Definition: AkDynaBlkPool.h:51
#define AkPlacementNew(_memory)
Definition: AkObject.h:49
#define AKASSERT(Condition)
Definition: AkAssert.h:67
void Delete(T *ptr)
T * New(A1 a1)
void RemoveItem(T *in_pItem, T *in_pPrevItem)
Remove an element.
Definition: AkListBare.h:402
T * New(A1 a1, A2 a2, A3 a3, A4 a4)
T * New(A1 a1, A2 a2, A3 a3)
#define SCRUB_NEW_ALLOC(pItem)
Definition: AkDynaBlkPool.h:62
uint32_t AkUInt32
Unsigned 32-bit integer.
void Transfer(AkDynaBlkPool< T, uPoolChunkSize, TAlloc > &in_src)
#define STATS_FREE()
Definition: AkDynaBlkPool.h:52
void Transfer(AkListBare< T, U_NEXTITEM, COUNT_POLICY, LAST_POLICY > &in_src)
Definition: AkListBare.h:437
T * New(A1 a1, A2 a2)

Was this page helpful?

Need Support?

Questions? Problems? Need more info? Contact us, and we can help!

Visit our Support page

Tell us about your project. We're here to help.

Register your project and we'll help you get started with no strings attached!

Get started with Wwise