00001 
00004 #ifndef FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KCONTAINERALLOCATORS_H
00005 #define FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KCONTAINERALLOCATORS_H
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 #include <fbxfilesdk/components/kbaselib/kbaselib_h.h>
00043 
00044 #include <fbxfilesdk/components/kbaselib/klib/kdebug.h>
00045 
00046 #include <stdlib.h>
00047 
00048 #include <fbxfilesdk/fbxfilesdk_nsbegin.h>
00049 
00054 class KFBX_DLL KBaseAllocator
00055 {
00056 public:
00063     KBaseAllocator(size_t const pRecordSize)
00064         : mRecordSize(pRecordSize)
00065     {
00066     }
00067 
00075     void Reserve(size_t const pRecordCount)
00076     {
00077     }
00078 
00084     void* AllocateRecords(size_t const pRecordCount = 1)
00085     {
00086         return malloc(pRecordCount * mRecordSize);
00087     }
00088 
00092     void FreeMemory(void* pRecord)
00093     {
00094         free(pRecord);
00095     }
00096 
00099     size_t GetRecordSize() const
00100     {
00101         return mRecordSize;
00102     }
00103 
00104     
00105     
00106 
00107 
00108 
00109 
00110 private:
00111     size_t mRecordSize;
00112 };
00113 
00119 class KHungryAllocator
00120 {
00121 public:
00122     KHungryAllocator(size_t pRecordSize)
00123         : mRecordSize(pRecordSize)
00124         , mData(NULL)
00125         , mRecordPoolSize(0)
00126     {
00127     }
00128 
00129     KHungryAllocator(const KHungryAllocator& pOther)
00130         : mRecordSize(pOther.mRecordSize)
00131         , mData(0)
00132         , mRecordPoolSize(pOther.mRecordPoolSize)
00133     {
00134     }
00135 
00136     ~KHungryAllocator()
00137     {
00138         MemoryBlock* lCurrent = mData;
00139         MemoryBlock* lNext = lCurrent ? lCurrent->mNextBlock : 0;
00140         while (lCurrent)
00141         {
00142             delete lCurrent;
00143             lCurrent = lNext;
00144             lNext = lCurrent ? lCurrent->mNextBlock : 0;
00145         }
00146     }
00147 
00148     void Reserve(size_t const pRecordCount)
00149     {
00150         MemoryBlock* lMem = new MemoryBlock(pRecordCount * mRecordSize);
00151         lMem->mNextBlock = mData;
00152         mData = lMem;
00153         mRecordPoolSize += pRecordCount;
00154     }
00155 
00156     void* AllocateRecords(size_t const pRecordCount = 1)
00157     {
00158         MemoryBlock* lBlock = mData;
00159         void* lRecord = NULL;
00160 
00161         while ((lBlock != NULL) &&
00162             ((lRecord = lBlock->GetChunk(pRecordCount * mRecordSize)) == NULL))
00163         {
00164             lBlock = lBlock->mNextBlock;
00165         }
00166 
00167         if (lRecord == NULL)
00168         {
00169             size_t lNumRecordToAllocate = mRecordPoolSize / 8 == 0 ? 2 : mRecordPoolSize / 8;
00170             if (lNumRecordToAllocate < pRecordCount)
00171             {
00172                 lNumRecordToAllocate = pRecordCount;
00173             }
00174             Reserve(lNumRecordToAllocate);
00175             lRecord = AllocateRecords(pRecordCount);
00176         }
00177 
00178         return lRecord;
00179     }
00180 
00181     void FreeMemory(void* pRecord)
00182     {
00183     }
00184 
00185     size_t GetRecordSize() const
00186     {
00187         return mRecordSize;
00188     }
00189 
00190     KHungryAllocator& operator=(const KHungryAllocator& pOther)
00191     {
00192         if( this != &pOther )
00193         {
00194             
00195             
00196             
00197             if( mRecordSize < pOther.mRecordSize )
00198             {
00199                 mRecordPoolSize = 0;
00200             }
00201 
00202             mRecordSize = pOther.mRecordSize;
00203         }
00204 
00205         return(*this);
00206     }
00207 
00208 private:
00209     class MemoryBlock
00210     {
00211     public:
00212         MemoryBlock(size_t pSize)
00213             : mNextBlock(NULL)
00214             , mData(NULL)
00215             , mFreeData(NULL)
00216             , mEnd(NULL)
00217         {
00218             mData = malloc(pSize);
00219             mFreeData = mData;
00220             mEnd = reinterpret_cast<char*>(mData) + pSize;
00221         };
00222 
00223         ~MemoryBlock()
00224         {
00225             free(mData);
00226         }
00227 
00228         void* GetChunk(size_t const pSize)
00229         {
00230             if (reinterpret_cast<char*>(mFreeData) + pSize < mEnd)
00231             {
00232                 void* lChunk = mFreeData;
00233                 mFreeData = reinterpret_cast<char*>(mFreeData) + pSize;
00234                 return lChunk;
00235             }
00236 
00237             return NULL;
00238         }
00239 
00240         MemoryBlock* mNextBlock;
00241         void* mData;
00242         void* mFreeData;
00243         void* mEnd;
00244     };
00245 
00246     size_t mRecordSize;
00247     MemoryBlock* mData;
00248     size_t mRecordPoolSize;
00249 };
00250 
00251 #include <fbxfilesdk/fbxfilesdk_nsend.h>
00252 
00253 #endif // FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KCONTAINERALLOCATORS_H
00254