fbxsdk/core/base/fbxcontainerallocators.h Source File
 
 
 
fbxsdk/core/base/fbxcontainerallocators.h
Go to the documentation of this file.
00001 /****************************************************************************************
00002  
00003    Copyright (C) 2013 Autodesk, Inc.
00004    All rights reserved.
00005  
00006    Use of this software is subject to the terms of the Autodesk license agreement
00007    provided at the time of installation or download, or which otherwise accompanies
00008    this software in either electronic or hard copy form.
00009  
00010 ****************************************************************************************/
00011 
00013 #ifndef _FBXSDK_CORE_BASE_CONTAINER_ALLOCATORS_H_
00014 #define _FBXSDK_CORE_BASE_CONTAINER_ALLOCATORS_H_
00015 
00016 #include <fbxsdk/fbxsdk_def.h>
00017 
00018 #include <fbxsdk/fbxsdk_nsbegin.h>
00019 
00023 class FBXSDK_DLL FbxBaseAllocator
00024 {
00025 public:
00032         FbxBaseAllocator(const size_t pRecordSize) :
00033                 mRecordSize(pRecordSize)
00034         {
00035         }
00036 
00044         void Reserve(const size_t /*pRecordCount*/)
00045         {
00046                 // By default, ignore all preallocating requests.
00047         }
00048 
00054         void* AllocateRecords(const size_t pRecordCount=1)
00055         {
00056                 return FbxMalloc(pRecordCount * mRecordSize);
00057         }
00058 
00062         void FreeMemory(void* pRecord)
00063         {
00064                 FbxFree(pRecord);
00065         }
00066 
00069         size_t GetRecordSize() const
00070         {
00071                 return mRecordSize;
00072         }
00073 
00074 private:
00075         size_t mRecordSize;
00076 };
00077 
00082 class FbxHungryAllocator
00083 {
00084 public:
00085         FbxHungryAllocator(size_t pRecordSize) :
00086                 mRecordSize(pRecordSize),
00087                 mRecordPoolSize(0),
00088                 mData(NULL)
00089         {
00090         }
00091 
00092         FbxHungryAllocator(const FbxHungryAllocator& pOther) :
00093                 mRecordSize(pOther.mRecordSize),
00094                 mRecordPoolSize(pOther.mRecordPoolSize),
00095                 mData(NULL)
00096         {
00097         }
00098 
00099         ~FbxHungryAllocator()
00100         {
00101                 MemoryBlock* lCurrent = mData;
00102                 MemoryBlock* lNext = lCurrent ? lCurrent->mNextBlock : 0;
00103                 while (lCurrent)
00104                 {
00105                         FbxDelete(lCurrent);
00106                         lCurrent = lNext;
00107                         lNext = lCurrent ? lCurrent->mNextBlock : 0;
00108                 }
00109         }
00110 
00111         void Reserve(const size_t pRecordCount)
00112         {
00113                 MemoryBlock* lMem = FbxNew< MemoryBlock >(pRecordCount* mRecordSize);
00114                 lMem->mNextBlock = mData;
00115                 mData = lMem;
00116                 mRecordPoolSize += pRecordCount;
00117         }
00118 
00119         void* AllocateRecords(const size_t pRecordCount = 1)
00120         {
00121                 MemoryBlock* lBlock = mData;
00122                 void* lRecord = NULL;
00123 
00124                 while( (lBlock != NULL) && ((lRecord = lBlock->GetChunk(pRecordCount * mRecordSize)) == NULL) )
00125                 {
00126                         lBlock = lBlock->mNextBlock;
00127                 }
00128 
00129                 if( lRecord == NULL )
00130                 {
00131                         size_t lNumRecordToAllocate = mRecordPoolSize / 8 == 0 ? 2 : mRecordPoolSize / 8;
00132                         if( lNumRecordToAllocate < pRecordCount )
00133                         {
00134                                 lNumRecordToAllocate = pRecordCount;
00135                         }
00136                         Reserve(lNumRecordToAllocate);
00137                         lRecord = AllocateRecords(pRecordCount);
00138                 }
00139                 return lRecord;
00140         }
00141 
00142         void FreeMemory(void* /*pRecord*/)
00143         {
00144                 // "Hungry": release memory only when the allocator is destroyed.
00145         }
00146 
00147         size_t GetRecordSize() const
00148         {
00149                 return mRecordSize;
00150         }
00151 
00152         FbxHungryAllocator& operator=(const FbxHungryAllocator& pOther)
00153         {
00154                 if( this != &pOther )
00155                 {
00156                         // The next call to AllocateRecords() may skip over currently reserved
00157                         // records if the size changes drastically, but otherwise GetChunk()
00158                         // is size-oblivious.
00159                         if( mRecordSize < pOther.mRecordSize )
00160                         {
00161                                 mRecordPoolSize = 0;
00162                         }
00163 
00164                         mRecordSize = pOther.mRecordSize;
00165                 }
00166                 return(*this);
00167         }
00168 
00169 private:
00170         class MemoryBlock
00171         {
00172         public:
00173                 MemoryBlock(size_t pSize) :
00174                         mNextBlock(NULL),
00175                         mData(NULL),
00176                         mFreeData(NULL),
00177                         mEnd(NULL)
00178                 {
00179                         mData = FbxMalloc(pSize);
00180                         mFreeData = mData;
00181                         mEnd = reinterpret_cast<char*>(mData) + pSize;
00182                 }
00183 
00184                 ~MemoryBlock()
00185                 {
00186                         FbxFree(mData);
00187                 }
00188 
00189                 void* GetChunk(const size_t pSize)
00190                 {
00191                         if( reinterpret_cast<char*>(mFreeData) + pSize < mEnd )
00192                         {
00193                                 void* lChunk = mFreeData;
00194                                 mFreeData = reinterpret_cast<char*>(mFreeData) + pSize;
00195                                 return lChunk;
00196                         }
00197                         return NULL;
00198                 }
00199 
00200                 MemoryBlock*    mNextBlock;
00201                 void*                   mData;
00202                 void*                   mFreeData;
00203                 void*                   mEnd;
00204         };
00205 
00206         size_t                  mRecordSize;
00207         size_t                  mRecordPoolSize;
00208         MemoryBlock*    mData;
00209 };
00210 
00211 #include <fbxsdk/fbxsdk_nsend.h>
00212 
00213 #endif /* _FBXSDK_CORE_BASE_CONTAINER_ALLOCATORS_H_ */