Version
menu_open
link
Wwise SDK 2022.1.12
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 
147 private:
148  T* Alloc()
149  {
150  FreeBlock* pItem = NULL;
151  PoolChunk* pChunk = NULL;
152 
153  pChunk = m_chunkList.First();
154  while (pChunk != NULL && pChunk->AllAllocd())
155  pChunk = pChunk->pNextLightItem;
156 
157  if (pChunk == NULL)
158  {
159  pChunk = (PoolChunk *) TAlloc::Alloc( sizeof( PoolChunk ) );
160  AkPlacementNew(pChunk) PoolChunk();
161  STATS_NEWCHUNK();
162  if (pChunk != NULL)
163  m_chunkList.AddFirst(pChunk);
164  }
165 
166  if (pChunk != NULL)
167  {
168  pItem = pChunk->freeList.First();
169  AKASSERT(pItem != NULL);
170  pChunk->freeList.RemoveFirst();
171  SCRUB_NEW_ALLOC(pItem);
172  STATS_ALLOC();
173  }
174 
175  return reinterpret_cast<T*>(pItem);
176  }
177 
178  void Free( T* pObj )
179  {
180  SCRUB_FREE_BLOCK((void*)pObj);
181 
182  FreeBlock* pItem = reinterpret_cast<FreeBlock*>(pObj);
183 
184  PoolChunk* pPrevChunk = NULL;
185  PoolChunk* pChunk = m_chunkList.First();
186  while (pChunk != NULL && !pChunk->BelongsTo(pItem))
187  {
188  pPrevChunk = pChunk;
189  pChunk = pChunk->pNextLightItem;
190  }
191 
192  AKASSERT(pChunk != NULL);
193  pChunk->freeList.AddFirst(pItem);
194  STATS_FREE();
195 
196  if (pChunk->AllFree())
197  {
198  m_chunkList.RemoveItem(pChunk, pPrevChunk);
199  pChunk->~PoolChunk();
200  TAlloc::Free( pChunk );
201  STATS_DELCHUNK();
202  }
203  }
204 
205  tChunkList m_chunkList;
206 
207 #ifdef AK_DYNA_BLK_STATS
208  void Stats_Alloc()
209  {
210  uCurrentUsedBytes += sizeof(T);
211  uPeakUsedBytes = AkMax(uCurrentUsedBytes, uPeakUsedBytes);
212  }
213  void Stats_NewChunk()
214  {
215  uCurrentAllocdBytes += sizeof(PoolChunk);
216  uPeakAllocdBytes = AkMax(uCurrentAllocdBytes, uPeakAllocdBytes);
217  }
218  void Stats_Free()
219  {
220  uCurrentUsedBytes -= sizeof(T);
221  }
222  void Stats_DelChunk()
223  {
224  uCurrentAllocdBytes -= sizeof(PoolChunk);
225  }
226 public:
227  AkUInt32 uPeakUsedBytes;
228  AkUInt32 uPeakAllocdBytes;
229  AkUInt32 uCurrentAllocdBytes;
230  AkUInt32 uCurrentUsedBytes;
231 #endif
232 };
233 
234 
235 #endif
AkForceInline T * First()
Get first element.
Definition: AkListBare.h:388
#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:400
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.
#define STATS_FREE()
Definition: AkDynaBlkPool.h:52
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