版本

menu_open

include/AK/Tools/Common/AkDynaBlkPool.h

Go to the documentation of this file.
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

此页面对您是否有帮助?

需要技术支持?

仍有疑问?或者问题?需要更多信息?欢迎联系我们,我们可以提供帮助!

查看我们的“技术支持”页面

介绍一下自己的项目。我们会竭力为您提供帮助。

来注册自己的项目,我们帮您快速入门,不带任何附加条件!

开始 Wwise 之旅