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_ */