Table of Contents

Wwise SDK 2018.1.11
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  Version: <VERSION> Build: <BUILDNUMBER>
25  Copyright (c) <COPYRIGHTYEAR> Audiokinetic Inc.
26 *******************************************************************************/
27 
28 #ifndef _AKBLOCKPOOL_H
29 #define _AKBLOCKPOOL_H
30 
34 
35 //
36 // AkDynaBlkPool - A dynamic block pool allocator which will grow (and shrink) in size in contiguous chunks of 'uPoolChunkSize' objects.
37 // - Fragmentation in the pool will prevent it from shrinking, but in many use cases this is acceptable.
38 //
39 
40 #ifdef _DEBUG
41 //#define AK_DYNA_BLK_STATS
42 #define AK_DYNA_BLK_SCRUB_MEM
43 #endif
44 
45 #ifdef AK_DYNA_BLK_STATS
46 #define STATS_ALLOC() Stats_Alloc()
47 #define STATS_NEWCHUNK() Stats_NewChunk()
48 #define STATS_FREE() Stats_Free()
49 #define STATS_DELCHUNK() Stats_DelChunk()
50 #else
51 #define STATS_ALLOC()
52 #define STATS_NEWCHUNK()
53 #define STATS_FREE()
54 #define STATS_DELCHUNK()
55 #endif
56 
57 #ifdef AK_DYNA_BLK_SCRUB_MEM
58 #define SCRUB_NEW_CHUNK() memset(&memory, 0xCC, sizeof(T)*uPoolChunkSize)
59 #define SCRUB_NEW_ALLOC(pItem) memset(pItem, 0xAA, sizeof(T))
60 #define SCRUB_FREE_BLOCK(pObj) memset(pObj, 0xDD, sizeof(T))
61 #else
62 #define SCRUB_NEW_CHUNK()
63 #define SCRUB_NEW_ALLOC(pItem)
64 #define SCRUB_FREE_BLOCK(pObj)
65 #endif
66 
67 template < typename T, AkUInt32 uPoolChunkSize, class TAlloc = ArrayPoolDefault>
68 class AkDynaBlkPool: public TAlloc
69 {
70  enum { kChunkMemoryBytes = sizeof(T)*uPoolChunkSize };
71 
72  struct FreeBlock
73  {
74  FreeBlock* pNextItem;
75  char padding[ sizeof(T) - sizeof(FreeBlock*) ];
76  };
78 
79  struct PoolChunk
80  {
81  PoolChunk() : pNextLightItem(NULL)
82  {
84  for( AkUInt32 i=0; i<uPoolChunkSize; ++i )
85  {
86  FreeBlock* pBlk = reinterpret_cast<FreeBlock*>( &memory ) + i;
87  freeList.AddFirst(pBlk);
88  }
89  }
90 
91  inline bool BelongsTo( FreeBlock* pMem ) const { return (AkUInt8*)pMem >= memory && (AkUInt8*)pMem < (memory+kChunkMemoryBytes); }
92  inline bool AllFree() const { return freeList.Length() == uPoolChunkSize; }
93  inline bool AllAllocd() const { return freeList.IsEmpty(); }
94 
95  AkUInt8 memory[ kChunkMemoryBytes ];
96  PoolChunk* pNextLightItem;
97  tFreeList freeList;
98  };
100 
101 public:
102 
103  T* New()
104  {
105  T* ptr = Alloc();
106  if (ptr) AkPlacementNew(ptr) T;
107  return ptr;
108  }
109 
110  template<typename A1>
111  T* New(A1 a1)
112  {
113  T* ptr = Alloc();
114  if (ptr) AkPlacementNew(ptr) T(a1);
115  return ptr;
116  }
117 
118  template<typename A1, typename A2>
119  T* New(A1 a1, A2 a2)
120  {
121  T* ptr = Alloc();
122  if (ptr) AkPlacementNew(ptr) T(a1, a2);
123  return ptr;
124  }
125 
126  template<typename A1, typename A2, typename A3>
127  T* New(A1 a1, A2 a2, A3 a3)
128  {
129  T* ptr = Alloc();
130  if (ptr) AkPlacementNew(ptr) T(a1, a2, a3);
131  return ptr;
132  }
133 
134  template<typename A1, typename A2, typename A3, typename A4>
135  T* New(A1 a1, A2 a2, A3 a3, A4 a4)
136  {
137  T* ptr = Alloc();
138  if (ptr) AkPlacementNew(ptr) T(a1,a2,a3,a4);
139  return ptr;
140  }
141 
142  void Delete(T* ptr)
143  {
144  ptr->~T();
145  Free(ptr);
146  }
147 
148 private:
149  T* Alloc()
150  {
151  FreeBlock* pItem = NULL;
152  PoolChunk* pChunk = NULL;
153 
154  pChunk = m_chunkList.First();
155  while (pChunk != NULL && pChunk->AllAllocd())
156  pChunk = pChunk->pNextLightItem;
157 
158  if (pChunk == NULL)
159  {
160  pChunk = (PoolChunk *) TAlloc::Alloc( sizeof( PoolChunk ) );
161  AkPlacementNew(pChunk) PoolChunk();
162  STATS_NEWCHUNK();
163  if (pChunk != NULL)
164  m_chunkList.AddFirst(pChunk);
165  }
166 
167  if (pChunk != NULL)
168  {
169  pItem = pChunk->freeList.First();
170  AKASSERT(pItem != NULL);
171  pChunk->freeList.RemoveFirst();
172  SCRUB_NEW_ALLOC(pItem);
173  STATS_ALLOC();
174  }
175 
176  return reinterpret_cast<T*>(pItem);
177  }
178 
179  void Free( T* pObj )
180  {
181  SCRUB_FREE_BLOCK((void*)pObj);
182 
183  FreeBlock* pItem = reinterpret_cast<FreeBlock*>(pObj);
184 
185  PoolChunk* pPrevChunk = NULL;
186  PoolChunk* pChunk = m_chunkList.First();
187  while (pChunk != NULL && !pChunk->BelongsTo(pItem))
188  {
189  pPrevChunk = pChunk;
190  pChunk = pChunk->pNextLightItem;
191  }
192 
193  AKASSERT(pChunk != NULL);
194  pChunk->freeList.AddFirst(pItem);
195  STATS_FREE();
196 
197  if (pChunk->AllFree())
198  {
199  m_chunkList.RemoveItem(pChunk, pPrevChunk);
200  pChunk->~PoolChunk();
201  TAlloc::Free( pChunk );
202  STATS_DELCHUNK();
203  }
204  }
205 
206  tChunkList m_chunkList;
207 
208 #ifdef AK_DYNA_BLK_STATS
209  void Stats_Alloc()
210  {
211  uCurrentUsedBytes += sizeof(T);
212  uPeakUsedBytes = AkMax(uCurrentUsedBytes, uPeakUsedBytes);
213  }
214  void Stats_NewChunk()
215  {
216  uCurrentAllocdBytes += sizeof(PoolChunk);
217  uPeakAllocdBytes = AkMax(uCurrentAllocdBytes, uPeakAllocdBytes);
218  }
219  void Stats_Free()
220  {
221  uCurrentUsedBytes -= sizeof(T);
222  }
223  void Stats_DelChunk()
224  {
225  uCurrentAllocdBytes -= sizeof(PoolChunk);
226  }
227 public:
228  AkUInt32 uPeakUsedBytes;
229  AkUInt32 uPeakAllocdBytes;
230  AkUInt32 uCurrentAllocdBytes;
231  AkUInt32 uCurrentUsedBytes;
232 #endif
233 };
234 
235 
236 #endif
#define STATS_NEWCHUNK()
Definition: AkDynaBlkPool.h:52
AKRESULT __cdecl Free(AkMemPoolId in_poolId, void *in_pMemAddress)
T * New(A1 a1, A2 a2, A3 a3, A4 a4)
Definition: AkDynaBlkPool.h:135
uint8_t AkUInt8
Unsigned 8-bit integer.
Definition: AkTypes.h:77
T * New()
Definition: AkDynaBlkPool.h:103
T * New(A1 a1, A2 a2)
Definition: AkDynaBlkPool.h:119
#define STATS_DELCHUNK()
Definition: AkDynaBlkPool.h:54
#define AKASSERT(Condition)
Definition: AkAssert.h:69
T * New(A1 a1, A2 a2, A3 a3)
Definition: AkDynaBlkPool.h:127
void Delete(T *ptr)
Definition: AkDynaBlkPool.h:142
void AddFirst(T *in_pItem)
Add element at the beginning of list.
Definition: AkListBare.h:304
#define STATS_ALLOC()
Definition: AkDynaBlkPool.h:51
T * New(A1 a1)
Definition: AkDynaBlkPool.h:111
#define NULL
Definition: AkTypes.h:49
#define STATS_FREE()
Definition: AkDynaBlkPool.h:53
#define AkPlacementNew(_memory)
Definition: AkObject.h:53
#define SCRUB_NEW_ALLOC(pItem)
Definition: AkDynaBlkPool.h:63
void RemoveItem(T *in_pItem, T *in_pPrevItem)
Remove an element.
Definition: AkListBare.h:396
#define AkMax(x1, x2)
Definition: AkPlatformFuncs.h:93
uint32_t AkUInt32
Unsigned 32-bit integer.
Definition: AkTypes.h:79
AkForceInline T * First()
Get first element.
Definition: AkListBare.h:384
#define SCRUB_NEW_CHUNK()
Definition: AkDynaBlkPool.h:62
#define SCRUB_FREE_BLOCK(pObj)
Definition: AkDynaBlkPool.h:64