00001 /******************************************************************************* 00002 The content of this file includes portions of the AUDIOKINETIC Wwise Technology 00003 released in source code form as part of the SDK installer package. 00004 00005 Commercial License Usage 00006 00007 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology 00008 may use this file in accordance with the end user license agreement provided 00009 with the software or, alternatively, in accordance with the terms contained in a 00010 written agreement between you and Audiokinetic Inc. 00011 00012 Apache License Usage 00013 00014 Alternatively, this file may be used under the Apache License, Version 2.0 (the 00015 "Apache License"); you may not use this file except in compliance with the 00016 Apache License. You may obtain a copy of the Apache License at 00017 http://www.apache.org/licenses/LICENSE-2.0. 00018 00019 Unless required by applicable law or agreed to in writing, software distributed 00020 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES 00021 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for 00022 the specific language governing permissions and limitations under the License. 00023 00024 Version: <VERSION> Build: <BUILDNUMBER> 00025 Copyright (c) <COPYRIGHTYEAR> Audiokinetic Inc. 00026 *******************************************************************************/ 00027 00028 #ifndef _AKBLOCKPOOL_H 00029 #define _AKBLOCKPOOL_H 00030 00031 #include <AK/Tools/Common/AkObject.h> 00032 #include <AK/Tools/Common/AkAssert.h> 00033 #include <AK/Tools/Common/AkListBareLight.h> 00034 00035 // 00036 // AkDynaBlkPool - A dynamic block pool allocator which will grow (and shrink) in size in contiguous chunks of 'uPoolChunkSize' objects. 00037 // - Fragmentation in the pool will prevent it from shrinking, but in many use cases this is acceptable. 00038 // 00039 00040 #ifdef _DEBUG 00041 //#define AK_DYNA_BLK_STATS 00042 #define AK_DYNA_BLK_SCRUB_MEM 00043 #endif 00044 00045 #ifdef AK_DYNA_BLK_STATS 00046 #define STATS_ALLOC() Stats_Alloc() 00047 #define STATS_NEWCHUNK() Stats_NewChunk() 00048 #define STATS_FREE() Stats_Free() 00049 #define STATS_DELCHUNK() Stats_DelChunk() 00050 #else 00051 #define STATS_ALLOC() 00052 #define STATS_NEWCHUNK() 00053 #define STATS_FREE() 00054 #define STATS_DELCHUNK() 00055 #endif 00056 00057 #ifdef AK_DYNA_BLK_SCRUB_MEM 00058 #define SCRUB_NEW_CHUNK() memset(&memory, 0xCC, sizeof(T)*uPoolChunkSize) 00059 #define SCRUB_NEW_ALLOC(pItem) memset(pItem, 0xAA, sizeof(T)) 00060 #define SCRUB_FREE_BLOCK(pObj) memset(pObj, 0xDD, sizeof(T)) 00061 #else 00062 #define SCRUB_NEW_CHUNK() 00063 #define SCRUB_NEW_ALLOC(pItem) 00064 #define SCRUB_FREE_BLOCK(pObj) 00065 #endif 00066 00067 template < typename T, AkUInt32 uPoolChunkSize, class TAlloc = ArrayPoolDefault> 00068 class AkDynaBlkPool: public TAlloc 00069 { 00070 enum { kChunkMemoryBytes = sizeof(T)*uPoolChunkSize }; 00071 00072 struct FreeBlock 00073 { 00074 FreeBlock* pNextItem; 00075 char padding[ sizeof(T) - sizeof(FreeBlock*) ]; 00076 }; 00077 typedef AkListBare< FreeBlock, AkListBareNextItem, AkCountPolicyWithCount, AkLastPolicyNoLast > tFreeList; 00078 00079 struct PoolChunk 00080 { 00081 PoolChunk() : pNextLightItem(NULL) 00082 { 00083 SCRUB_NEW_CHUNK(); 00084 for( AkUInt32 i=0; i<uPoolChunkSize; ++i ) 00085 { 00086 FreeBlock* pBlk = reinterpret_cast<FreeBlock*>( &memory ) + i; 00087 freeList.AddFirst(pBlk); 00088 } 00089 } 00090 00091 inline bool BelongsTo( FreeBlock* pMem ) const { return (AkUInt8*)pMem >= memory && (AkUInt8*)pMem < (memory+kChunkMemoryBytes); } 00092 inline bool AllFree() const { return freeList.Length() == uPoolChunkSize; } 00093 inline bool AllAllocd() const { return freeList.IsEmpty(); } 00094 00095 AkUInt8 memory[ kChunkMemoryBytes ]; 00096 PoolChunk* pNextLightItem; 00097 tFreeList freeList; 00098 }; 00099 typedef AkListBareLight< PoolChunk > tChunkList; 00100 00101 public: 00102 00103 T* New() 00104 { 00105 T* ptr = Alloc(); 00106 if (ptr) AkPlacementNew(ptr) T; 00107 return ptr; 00108 } 00109 00110 template<typename A1> 00111 T* New(A1 a1) 00112 { 00113 T* ptr = Alloc(); 00114 if (ptr) AkPlacementNew(ptr) T(a1); 00115 return ptr; 00116 } 00117 00118 template<typename A1, typename A2> 00119 T* New(A1 a1, A2 a2) 00120 { 00121 T* ptr = Alloc(); 00122 if (ptr) AkPlacementNew(ptr) T(a1, a2); 00123 return ptr; 00124 } 00125 00126 template<typename A1, typename A2, typename A3> 00127 T* New(A1 a1, A2 a2, A3 a3) 00128 { 00129 T* ptr = Alloc(); 00130 if (ptr) AkPlacementNew(ptr) T(a1, a2, a3); 00131 return ptr; 00132 } 00133 00134 template<typename A1, typename A2, typename A3, typename A4> 00135 T* New(A1 a1, A2 a2, A3 a3, A4 a4) 00136 { 00137 T* ptr = Alloc(); 00138 if (ptr) AkPlacementNew(ptr) T(a1,a2,a3,a4); 00139 return ptr; 00140 } 00141 00142 void Delete(T* ptr) 00143 { 00144 ptr->~T(); 00145 Free(ptr); 00146 } 00147 00148 private: 00149 T* Alloc() 00150 { 00151 FreeBlock* pItem = NULL; 00152 PoolChunk* pChunk = NULL; 00153 00154 pChunk = m_chunkList.First(); 00155 while (pChunk != NULL && pChunk->AllAllocd()) 00156 pChunk = pChunk->pNextLightItem; 00157 00158 if (pChunk == NULL) 00159 { 00160 pChunk = (PoolChunk *) TAlloc::Alloc( sizeof( PoolChunk ) ); 00161 AkPlacementNew(pChunk) PoolChunk(); 00162 STATS_NEWCHUNK(); 00163 if (pChunk != NULL) 00164 m_chunkList.AddFirst(pChunk); 00165 } 00166 00167 if (pChunk != NULL) 00168 { 00169 pItem = pChunk->freeList.First(); 00170 AKASSERT(pItem != NULL); 00171 pChunk->freeList.RemoveFirst(); 00172 SCRUB_NEW_ALLOC(pItem); 00173 STATS_ALLOC(); 00174 } 00175 00176 return reinterpret_cast<T*>(pItem); 00177 } 00178 00179 void Free( T* pObj ) 00180 { 00181 SCRUB_FREE_BLOCK((void*)pObj); 00182 00183 FreeBlock* pItem = reinterpret_cast<FreeBlock*>(pObj); 00184 00185 PoolChunk* pPrevChunk = NULL; 00186 PoolChunk* pChunk = m_chunkList.First(); 00187 while (pChunk != NULL && !pChunk->BelongsTo(pItem)) 00188 { 00189 pPrevChunk = pChunk; 00190 pChunk = pChunk->pNextLightItem; 00191 } 00192 00193 AKASSERT(pChunk != NULL); 00194 pChunk->freeList.AddFirst(pItem); 00195 STATS_FREE(); 00196 00197 if (pChunk->AllFree()) 00198 { 00199 m_chunkList.RemoveItem(pChunk, pPrevChunk); 00200 pChunk->~PoolChunk(); 00201 TAlloc::Free( pChunk ); 00202 STATS_DELCHUNK(); 00203 } 00204 } 00205 00206 tChunkList m_chunkList; 00207 00208 #ifdef AK_DYNA_BLK_STATS 00209 void Stats_Alloc() 00210 { 00211 uCurrentUsedBytes += sizeof(T); 00212 uPeakUsedBytes = AkMax(uCurrentUsedBytes, uPeakUsedBytes); 00213 } 00214 void Stats_NewChunk() 00215 { 00216 uCurrentAllocdBytes += sizeof(PoolChunk); 00217 uPeakAllocdBytes = AkMax(uCurrentAllocdBytes, uPeakAllocdBytes); 00218 } 00219 void Stats_Free() 00220 { 00221 uCurrentUsedBytes -= sizeof(T); 00222 } 00223 void Stats_DelChunk() 00224 { 00225 uCurrentAllocdBytes -= sizeof(PoolChunk); 00226 } 00227 public: 00228 AkUInt32 uPeakUsedBytes; 00229 AkUInt32 uPeakAllocdBytes; 00230 AkUInt32 uCurrentAllocdBytes; 00231 AkUInt32 uCurrentUsedBytes; 00232 #endif 00233 }; 00234 00235 00236 #endif
Questions? Problems? Need more info? Contact us, and we can help!
Visit our Support pageRegister your project and we'll help you get started with no strings attached!
Get started with Wwise