バージョン
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 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) 00107 AkPlacementNew(ptr) T; 00108 return ptr; 00109 } 00110 00111 void Delete(T* ptr) 00112 { 00113 ptr->~T(); 00114 Free(ptr); 00115 } 00116 00117 private: 00118 T* Alloc() 00119 { 00120 FreeBlock* pItem = NULL; 00121 PoolChunk* pChunk = NULL; 00122 00123 pChunk = m_chunkList.First(); 00124 while (pChunk != NULL && pChunk->AllAllocd()) 00125 pChunk = pChunk->pNextLightItem; 00126 00127 if (pChunk == NULL) 00128 { 00129 pChunk = (PoolChunk *) TAlloc::Alloc( sizeof( PoolChunk ) ); 00130 AkPlacementNew(pChunk) PoolChunk(); 00131 STATS_NEWCHUNK(); 00132 if (pChunk != NULL) 00133 m_chunkList.AddFirst(pChunk); 00134 } 00135 00136 if (pChunk != NULL) 00137 { 00138 pItem = pChunk->freeList.First(); 00139 AKASSERT(pItem != NULL); 00140 pChunk->freeList.RemoveFirst(); 00141 SCRUB_NEW_ALLOC(pItem); 00142 STATS_ALLOC(); 00143 } 00144 00145 return reinterpret_cast<T*>(pItem); 00146 } 00147 00148 void Free( T* pObj ) 00149 { 00150 SCRUB_FREE_BLOCK((void*)pObj); 00151 00152 FreeBlock* pItem = reinterpret_cast<FreeBlock*>(pObj); 00153 00154 PoolChunk* pPrevChunk = NULL; 00155 PoolChunk* pChunk = m_chunkList.First(); 00156 while (pChunk != NULL && !pChunk->BelongsTo(pItem)) 00157 { 00158 pPrevChunk = pChunk; 00159 pChunk = pChunk->pNextLightItem; 00160 } 00161 00162 AKASSERT(pChunk != NULL); 00163 pChunk->freeList.AddFirst(pItem); 00164 STATS_FREE(); 00165 00166 if (pChunk->AllFree()) 00167 { 00168 m_chunkList.RemoveItem(pChunk, pPrevChunk); 00169 pChunk->~PoolChunk(); 00170 TAlloc::Free( pChunk ); 00171 STATS_DELCHUNK(); 00172 } 00173 } 00174 00175 tChunkList m_chunkList; 00176 00177 #ifdef AK_DYNA_BLK_STATS 00178 void Stats_Alloc() 00179 { 00180 uCurrentUsedBytes += sizeof(T); 00181 uPeakUsedBytes = AkMax(uCurrentUsedBytes, uPeakUsedBytes); 00182 } 00183 void Stats_NewChunk() 00184 { 00185 uCurrentAllocdBytes += sizeof(PoolChunk); 00186 uPeakAllocdBytes = AkMax(uCurrentAllocdBytes, uPeakAllocdBytes); 00187 } 00188 void Stats_Free() 00189 { 00190 uCurrentUsedBytes -= sizeof(T); 00191 } 00192 void Stats_DelChunk() 00193 { 00194 uCurrentAllocdBytes -= sizeof(PoolChunk); 00195 } 00196 public: 00197 AkUInt32 uPeakUsedBytes; 00198 AkUInt32 uPeakAllocdBytes; 00199 AkUInt32 uCurrentAllocdBytes; 00200 AkUInt32 uCurrentUsedBytes; 00201 #endif 00202 }; 00203 00204 00205 #endif