Memory.h

Go to the documentation of this file.
00001 #ifndef __LDK_MEMORY_HH__
00002 #define __LDK_MEMORY_HH__
00003 
00005 //   Copyright (C) 2003-2006 Lorien Dunn.
00006 //
00007 //   Contact: loriendunn AT users DOT sourceforge DOT net
00008 //
00009 //   This software is provided 'as-is', without any express or implied warranty.
00010 //   In no event will the authors be held liable for any damages arising from
00011 //   the use of this software.
00012 //
00013 //   Permission is granted to anyone to use this software for any purpose,
00014 //   including commercial applications, and to alter it and redistribute it
00015 //   freely, subject to the following restrictions:
00016 //
00017 //   1. The origin of this software must not be misrepresented; you must not
00018 //   claim that you wrote the original software. If you use this software in a
00019 //   product, an acknowledgment in the product documentation would be
00020 //   appreciated but is not required.
00021 //
00022 //   2. Altered source versions must be plainly marked as such, and must not be
00023 //   misrepresented as being the original software.
00024 //
00025 //   3. This notice may not be removed or altered from any source distribution.
00026 //
00028 
00033 #include "LDK/Types.h"
00034 #include "LDK/Threading.h"
00035 #include "LDK/TemplateMeta.h"
00036 #include "LDK/Singletons.h"
00037 #include "LDK/Exceptions.h"
00038 #include <vector>
00039 #include <list>
00040 
00041 //not using <cname> headers because they cause
00042 //compatibility issues when including normal c header files.
00043 #include <string.h> //for memcpy,
00044 #include <assert.h>
00045 
00046 #ifdef DEBUG
00047 #define LDK_TRACK_ALLOCATION
00048 #endif //DEBUG
00049 
00050 namespace LDK
00051 {
00052 
00053 //All memory will be aligned on 16 byte boundaries. Do not change.
00054 #define BYTE_ALIGNMENT 16
00055 
00056 
00057 //You might want to change these according to your needs.
00058 //However if you do the whole library (and everything
00059 //which uses it will need to be recompiled or things
00060 //will get very strange indeed...
00061 //Chunk sizes should be be powers of two or memory alignment
00062 //will likely be completely wrong, and smaller than 16 bytes
00063 //on 32-bit systems and 32 bytes on 64-bit systems
00064 //will mean more space wasted than allocated for the Pools
00065 //with the smaller chunkSizes.
00066 
00067 #define LDK_SPARE_HEAPS 30
00068 #ifdef THIRTY_TWO_BIT
00069 #define LDK_HEAPSIZE_K 512
00070 #define LDK_MINCHUNKSIZE 16
00071 #elif defined SIXTY_FOUR_BIT
00072 #define LDK_HEAPSIZE_K 1024
00073 #define LDK_MINCHUNKSIZE 32
00074 #endif //THIRTY_TWO_BIT
00075 
00076 #define LDK_MAXCHUNKSIZE ((LDK_HEAPSIZE_K*1024)/2)
00077 
00078 //do a little preprocessor sanity checking.
00079 //Real power-of-2 and power-of-2 + 1/2-power-of-2 sanity
00080 //checking is done with a template metaprogram.
00081 
00082 #if LDK_HEAPSIZE_K % 2 != 0
00083     #error "LDK_HEAPSIZE_K must be even"
00084 #endif //LDK_HEAPSIZE_K % 2 == 0
00085 
00086 #if LDK_MAXCHUNKSIZE < LDK_MINCHUNKSIZE
00087     #error "LDK_MAXCHUNKSIZE < LDK_MINCHUNKSIZE"
00088 #endif //LDK_MAXCHUNKSIZE < LDK_MINCHUNKSIZE
00089 
00090 #if LDK_MINCHUNKSIZE % 2 != 0
00091     #error "LDK_MINCHUNKSIZE must be even"
00092 #endif //LDK_MINCHUNKSIZE % 2 != 0
00093 
00094 #if LDK_MAXCHUNKSIZE % 2 != 0
00095     #warning "LDK_MAXCHUNKSIZE must be even"
00096 #endif //LDK_MAXCHUNKSIZE % 2 != 0
00097 
00098 #if LDK_MAXCHUNKSIZE / 1024 > LDK_HEAPSIZE_K
00099     #error "LDK_MAXCHUNKSIZE / 1024 > HEAP_SIZE"
00100 #endif //LDK_MAXCHUNKSIZE / 1024 > LDK_HEAPSIZE_K
00101 
00102 #ifdef THIRTY_TWO_BIT
00103     #if LDK_MINCHUNKSIZE < 16
00104         #warning "minimum chunk size is less than housekeeping size"
00105     #endif //LDK_MINCHUNKSIZE < 16
00106 #elif defined SIXTY_FOUR_BIT
00107     #if LDK_MINCHUNKSIZE < 32
00108         #warning "minimum chunk size is less than housekeeping size"
00109     #endif //LDK_MINCHUNKSIZE < 32
00110 #endif //THIRTY_TWO_BIT
00111 
00112 #define MAX_CHUNKS_PER_HEAP (LDK_HEAPSIZE_K/ LDK_MINCHUNKSIZE)
00113 
00114 
00115 //Portability functions for allocating memory aligned on a
00116 //particular byte boundary. This allocation system always
00117 //uses 16-byte alignment. Memory allocated by this function
00118 //is not tracked.
00119 LDK_API void* alignedAlloc(size_t bytes, size_t align=BYTE_ALIGNMENT);
00120 LDK_API void  alignedFree(void *mem);
00121 //A wrapper function for alignedAlloc that places a Node structure
00122 //prior to the usable memory.The Node structure makes the allocation
00123 //able to be freed and realloced by LDK::dealloc and LDK::realloc.
00124 inline void* bigAlloc(size_t size);
00125 
00126 class LDK_API MetaPool;
00127 
00128 namespace Details
00129 {
00130 
00131 class LDK_API Heap;
00133 //                                                                    //
00134 //      Struct Node. A header for a chunk and also a linked           //
00135 //      list node. The list structure eliminates searching for        //
00136 //      free chunks.                                                  //
00137 //                                                                    //
00139 
00140 struct LDK_API Node
00141 {
00142     //Holds the actual size of the allocation to speed up realloc
00143     //and test if free
00144     size_t          mAllocSize;
00145     //next node in this heap
00146     Node*           mNext;
00147     //heap that owns this node (BIG freeChunk speedup)
00148     Heap*           mHeap;
00149     //Used to assert if a different thread to the allocating
00150     //thread attempts to delete this piece of memory
00151     size_t          mThreadID;
00152 };
00153 
00154 
00155 /*
00156 ** NB I use c-style casts in places because it is much
00157 ** easier to read. IMHO the reinterpret_cast syntax
00158 ** was never designed for such crazy casting.
00159 */
00160 
00161 //Finds the mHeap member in the node that this memory
00162 //belongs to.
00163 inline Heap* getOwnerHeap(void* mem)
00164 {
00165     // *(Heap**) (((char*)mem) - HeapOffsetIntoNodeInBytes);
00166     return *(Heap**) (((char*)mem) - sizeof(size_t) - sizeof(Heap*));
00167 }
00168 
00169 //returns the Node that owns this memory.
00170 inline Node* getNode(void* mem)
00171 {
00172     return (Node*)(((char*)mem) - sizeof(Node));
00173 }
00174 
00175 class LDK_API Pool;
00176 
00178 //                                                                    //
00179 //      Class Heap. Uses a very strange and (eventually) tangled      //
00180 //      linked list of nodes and chunks that get allocated as         //
00181 //      one block of ram, arranged like this:                         //
00182 //                                                                    //
00183 //      |--------------|    The tangle comes from nodes and chunks    //
00184 //      |     Node     |    being reused, and the linked list means   //
00185 //      |--------------|    there is no searching through the heap    //
00186 //      |  Allocated   |    for a free node/chunk combination.        //
00187 //      |    chunk     |    The nodes are headers for the chunks      //
00188 //      |--------------|                                              //
00189 //      |  Next Node   |                                              //
00190 //      |--------------|                                              //
00191 //      |Next Allocated|                                              //
00192 //      |    chunk     |                                              //
00193 //      |--------------|                                              //
00194 //                                                                    //
00196 
00197 class LDK_API Heap
00198 {
00199     friend class LDK_API Pool;
00200     //the mem that gets split into Nodes and chunks
00201     void*   mMemory;
00202     //sizeof(Node) + chunkSize
00203     size_t  mNodeSize;
00204     //the next unused node
00205     Node*   mNextFree;
00206     //the last node in the heap
00207     Node*   mLastNode;
00208     //the size of the mem chunks this heap contains
00209     size_t  mChunkSize;
00210     //the noOfChunks in this heap that have been allocated
00211     size_t  mAllocCount;
00212     //the max allocs this heap can hold
00213     size_t  mMaxAllocs;
00214     //used in cleanup phase
00215     Pool*   mParent;
00216     //the requested heapSize
00217     const size_t mSizeInBytes;
00218     //size of the heap + sizeof the max possible no of nodes
00219     const size_t mRealSize;
00220 
00221     void setup(Pool* parent, size_t chunkSize);
00222 
00223 
00224 public:
00225 
00226     //make sure this thing throws BadAllocError
00227     inline void* operator new(size_t size)
00228     {
00229         void* mem = malloc(size);
00230         if(!mem)
00231             throw LDK_BADALLOC_ERROR;
00232         return mem;
00233     }
00234 
00235     inline void operator delete(void* mem)
00236     {
00237         assert(mem);
00238         ::free(mem);
00239     }
00240 
00241     inline Heap(Pool* parent, size_t chunkSize, size_t size) :
00242      mMemory(NULL),
00243      mChunkSize(chunkSize),
00244      mSizeInBytes(size),
00245      mRealSize(size+(MAX_CHUNKS_PER_HEAP*sizeof(Node)))
00246     {
00247         mMemory = alignedAlloc(mRealSize);
00248         setup(parent, chunkSize);
00249     }
00250 
00251     inline ~Heap()
00252     {
00253         if(mMemory)
00254             alignedFree(mMemory);
00255     }
00256 
00257     //makes a node and chunk appear as one block of memory,
00258     //and a heap as an array of them. mNodeSize is sizeof(Node)
00259     //plus the size of the chunk.
00260     inline Node* operator[](size_t idx) const
00261     {
00262         return reinterpret_cast<Node*>((char*)mMemory + (idx*mNodeSize));
00263     }
00264 
00265     inline size_t chunkSize() const { return mChunkSize; }
00266 
00267     inline size_t sizeInBytes() const { return mSizeInBytes; }
00268 
00269     inline size_t allocCount() const { return mAllocCount; }
00270 
00271     inline size_t maxAllocs() const { return mMaxAllocs; }
00272 
00273     inline bool full() const { return !mNextFree; }
00274 
00275     inline bool empty() const { return mAllocCount == 0; }
00276 
00277     //Returns a free chunk from this heap and sets up the next
00278     //allocation. This method will never be called if mNextFree
00279     //is NULL
00280     inline void* allocChunk(size_t allocSize)
00281     {
00282         void *chunk = NULL;
00283         mNextFree->mAllocSize = allocSize;
00284         #ifndef NDEBUG
00285         mNextFree->mThreadID = currentThreadID();
00286         #endif
00287         chunk = (void*)(((char*)mNextFree) + sizeof(Node));
00288         mNextFree = mNextFree->mNext;
00289         mAllocCount++;
00290         return chunk;
00291     }
00292 
00293     //Frees a chunk of memory and sets up all the pointers so no
00294     //searching for free chunks is needed. This is what causes
00295     //the tangles in the list. When the heap this belongs to is
00296     //empty it gets passed to the parent pool for re-use.
00297     void freeChunk(void *mem);
00298 };
00299 
00301 //                                                                    //
00302 //      Class Pool. Manages a vector of (equal chunkSize) heaps       //
00303 //      for allocation, also facilitates recycling of heaps both      //
00304 //      within itself and though MetaPool.                            //
00305 //                                                                    //
00307 
00308 class LDK_API Pool
00309 {
00310 protected:
00311     friend class LDK_API Heap;
00312     friend class LDK_API LDK::MetaPool; //g++-4.1 insists on LDK:: here... Odd.
00313     Heap* mCurrentHeap;
00314     Heap* mSpareHeap; //to avoid calling Heap::setup when there is no need
00315     size_t mChunkSize;
00316     MetaPool* mParent;
00317     const size_t mDefaultHeapSize;
00318 #ifdef _MSC_VER
00319 #pragma warning (disable : 4251)
00320 #endif
00321     typedef std::vector<Heap*,MallocAllocator<Heap*> > HeapVector;
00322     HeapVector mHeaps;
00323 #ifdef _MSC_VER
00324 #pragma warning (default : 4251)
00325 #endif
00326 
00327     //When a heap is completely empty try putting it in the
00328     //mSpareHeap member (so setup doesn't have to be called).
00329     //If mSpareHeap is already used, add the heap to a LIFO
00330     //in MetaPool for re-use elsewhere.
00331     void cleanup(Heap* h);
00332 
00333 public:
00334 
00335     Pool(MetaPool* parent, size_t chunkSize, size_t defaultHeapSize);
00336     ~Pool();
00337 
00338     //Find a heap with a reasonable numer of free slots. If none
00339     //are free allocates a new heap as a last resort, hence could
00340     //throw BadAllocError. Implemented after MetaPool.
00341     void findHeap();
00342 
00343     //Returns a free chunk. Can throw BadAllocError.
00344     //Contains the only branches I can't remove in mempry present conditions.
00345     //Will trigger plenty more branches if mCurrentHeap is full though.
00346     inline void *allocChunk(size_t allocSize)
00347     {
00348         if(!mCurrentHeap || mCurrentHeap->full())
00349             findHeap();
00350         return mCurrentHeap->allocChunk(allocSize);
00351     }
00352 
00353     inline size_t chunkSize() const { return mChunkSize; }
00354     inline size_t noOfHeaps() const { return mHeaps.size(); }
00355     inline size_t defaultHeapSize() const { return mDefaultHeapSize; }
00356 };
00357 
00358 
00359 
00360 /***********************************************************************
00361 **                                                                    **
00362 **            Begin template metaprogramming                          **
00363 **                                                                    **
00364 ***********************************************************************/
00365 
00366 #define MIN_CHUNKSIZE LDK_MINCHUNKSIZE
00367 #define MAX_CHUNKSIZE LDK_MAXCHUNKSIZE
00368 
00370 //      Calculate (compile time) the number of pools required       //
00372 
00373 template <int Size>
00374 struct PoolCount
00375 {
00376     enum { value = PoolCount<Size/2>::value + 1 };
00377 };
00378 
00379 //These terminates the above loop
00380 template <>
00381 struct LDK_API PoolCount<MIN_CHUNKSIZE>
00382 {
00383     enum { value = 1 };
00384 };
00385 
00386 template <>
00387 struct LDK_API PoolCount<(MIN_CHUNKSIZE+(MIN_CHUNKSIZE/2))>
00388 {
00389     enum { value = 1 };
00390 };
00391 
00392 template <>
00393 struct LDK_API PoolCount<(MIN_CHUNKSIZE+(MIN_CHUNKSIZE/3))>
00394 {
00395     enum { value = 1 };
00396 };
00397 
00398 //provides easy acces to the compile time calculated number of
00399 //pools
00400 struct LDK_API NoOfPools
00401 {
00402     enum
00403     {
00404         max = MAX_CHUNKSIZE,
00405         maxIsPowerOf2 = Meta::PowerOf2<max>::value,
00406         pwrOf2 = PoolCount<(maxIsPowerOf2 ? max : (max-(max/3)))>::value,
00407         notPwrOf2 = PoolCount<(maxIsPowerOf2 ? (max-(max/4)) : max)>::value,
00408         value = pwrOf2 + notPwrOf2
00409     };
00410 };
00411 
00413 //      Calculate (compile time) the chunkSize of the pool at Idx    //
00415 template <int Idx>
00416 class ChunkSize
00417 {
00418     struct MinChunkPowerOf2
00419     {
00420         enum
00421         {
00422             powerOf2 = !(Idx%2),
00423             value = powerOf2 ? ChunkSize<Idx+1>::value - ChunkSize<Idx+1>::value/3 :\
00424                 ChunkSize<Idx+1>::value - ChunkSize<Idx+1>::value/4
00425         };
00426     };
00427     struct MinChunkNotPowerOf2
00428     {
00429         enum
00430         {
00431             powerOf2 = Idx%2,
00432             value = powerOf2 ? ChunkSize<Idx+1>::value - ChunkSize<Idx+1>::value/3 :\
00433                 ChunkSize<Idx+1>::value - ChunkSize<Idx+1>::value/4
00434         };
00435     };
00436 public:
00437     enum
00438     {
00439         value = Meta::If<Meta::PowerOf2<MIN_CHUNKSIZE>::value, MinChunkPowerOf2,\
00440             MinChunkNotPowerOf2>::result::value
00441     };
00442 };
00443 
00444 //This terminates the above loop
00445 template<>
00446 class LDK_API ChunkSize<NoOfPools::value>
00447 {
00448     struct LDK_API MaxChunkPowerOf2
00449     {
00450         enum { value = MAX_CHUNKSIZE + (MAX_CHUNKSIZE/2) };
00451     };
00452     struct LDK_API MaxChunkNotPowerOf2
00453     {
00454         enum { value = MAX_CHUNKSIZE + (MAX_CHUNKSIZE/3) };
00455     };
00456 public:
00457     enum
00458     {
00459         value = Meta::If<Meta::PowerOf2<MAX_CHUNKSIZE>::value,\
00460             MaxChunkPowerOf2, MaxChunkNotPowerOf2>::result::value
00461     };
00462 };
00463 
00465 // Calculate (compile time) the best pool Idx to allocate Size bytes //
00467 template
00468 <
00469     int NoOfPools,
00470     int Size,
00471     int Idx=0
00472 >
00473 struct PoolIdxSearch
00474 {
00475     enum
00476     {
00477         //will the requested alloc fit in a chunk?
00478         inRange = Size <=  MAX_CHUNKSIZE? true : false,
00479         //does the alloc fit in a pool, and it will fit in the current pool?
00480         fitsHereToo = (inRange && (Size < ChunkSize<Idx>::value)) ? true : false,
00481         //if it does return the current index, otherwise keep recursing
00482         value =  fitsHereToo ? Idx : PoolIdxSearch<NoOfPools,Size,Idx+1>::value
00483     };
00484 };
00485 
00486 //terminate the loop at NoOfPools::value, which means we have to use
00487 //the run-time allocator because there isn't a pool large enough
00488 template <int Size>
00489 struct PoolIdxSearch<NoOfPools::value,Size,NoOfPools::value>
00490 {
00491     enum { value = -1 };
00492 };
00493 
00494 #undef MIN_CHUNKSIZE
00495 #undef MAX_CHUNKSIZE
00496 
00497 /***********************************************************************
00498 **                                                                    **
00499 **              End template metaprogramming                          **
00500 **                                                                    **
00501 ***********************************************************************/
00502 
00503 } //namespace Details
00504 
00506 //                                                                    //
00507 //     Class MetaPool. Encapsulates multiple pools of different       //
00508 //     chunkSizes, handles runtime searching for the best size        //
00509 //     pool for an alloc, and manages recylcling of heaps between     //
00510 //     pools with different chunkSizes.                               //
00511 //                                                                    //
00513 #ifdef _MSC_VER //non exported members
00514 #pragma warning (disable : 4251)
00515 #endif
00516 class LDK_API MetaPool
00517 {
00518 private:
00519 
00520     friend class LDK_API Details::Pool;
00521 
00522     typedef Details::NoOfPools NoOfPools;
00523 
00524     //holds all the pools
00525     Details::Pool* mPools[NoOfPools::value];
00526 
00527     //some space to store empty heaps for re-use between
00528     //pools. Using a vector as a LIFO because of constant-time
00529     //pop_back() and ability to reserve space (which deque can't)
00530 
00531     typedef std::vector<Details::Heap*,MallocAllocator<Details::Heap*> > HeapVector;
00532     HeapVector mSpareHeaps;
00533 
00534     #ifdef LDK_TRACK_ALLOCATION
00535     struct TrackedAlloc
00536     {
00537         void* mMem;
00538         int   mLine;
00539         char  mFile[128];
00540 
00541         inline TrackedAlloc(const char* file=NULL, int line=0, void* mem=NULL)
00542         {
00543             mMem = mem;
00544             mLine = line;
00545             mFile[127]= '\0';
00546             strncpy(mFile,file,127);
00547         }
00548     };
00549     typedef std::list<TrackedAlloc,MallocAllocator<TrackedAlloc> > AllocList;
00550     AllocList mAllocs;
00551     #endif
00552 
00553 
00554     void addSpareHeap(Details::Heap* h);
00555     Details::Heap* findSpareHeap(size_t chunkSize);
00556 
00557 public:
00558     #ifdef LDK_TRACK_ALLOCATION
00559     inline void trackAlloc(const char* file, int line, void* mem)
00560     {
00561         mAllocs.push_back(TrackedAlloc(file,line,mem));
00562     }
00563 
00564     inline void untrackAlloc(void* mem)
00565     {
00566         AllocList::iterator i = mAllocs.end();
00567         if(!mAllocs.empty())
00568         {
00569             i--;
00570             while(i != mAllocs.begin())
00571             {
00572                 if((*i).mMem == mem)
00573                 {
00574                     mAllocs.erase(i);
00575                     return;
00576                 }
00577                 i--;
00578             }
00579             if((*i).mMem == mem)
00580             {
00581                 mAllocs.erase(i);
00582                 return;
00583             }
00584         }
00585     }
00586     //called by ~MetaPool. Prints to the native stdout (not via the
00587     //VFileSystem).
00588     void dumpAllocs();
00589     #endif
00590 
00591     inline Details::Pool* pool(int idx)
00592     {
00593         return mPools[idx];
00594     }
00595 
00596     MetaPool();
00597     ~MetaPool();
00598 
00599     //Allocate size bytes (from a pool if possible). Can throw BadAllocError.
00600     void* alloc(const char* file, int line, size_t size);
00601 
00602     //Resize an allocation. This WILL crash if you pass it memory
00603     //that was not allocated through this allocation system.
00604     void* realloc(const char* file, int line, void *mem, size_t newSize);
00605 
00606     //Free an allocation. This WILL crash if you pass it memory
00607     //that was not allocated through this allocation system.
00608     void dealloc(void *mem)
00609     {
00610         if(mem)
00611         {
00612             #ifdef LDK_TRACK_ALLOCATION
00613             untrackAlloc(mem);
00614             #endif
00615             Details::Heap *h = Details::getOwnerHeap(mem);
00616             if(!h)
00617             {
00618                 alignedFree(Details::getNode(mem));
00619                 return;
00620             }
00621             h->freeChunk(mem);
00622         }
00623     }
00624 };
00625 #ifdef _MSC_VER
00626 #pragma warning (default : 4251)
00627 #endif
00628 
00629 typedef Singleton<MetaPool> MemorySingleton;
00630 
00631 //This struct will be the result of an If template if the
00632 //requested size will fit in a pool.
00633 template<int Idx>
00634 struct CTAllocHelper
00635 {
00636     inline static void* alloc(const char* file, int line, size_t size)
00637     {
00638         MetaPool& mp = MemorySingleton::instance();
00639         void* mem = mp.pool(Idx)->allocChunk(size);
00640         #ifdef LDK_TRACK_ALLOCATION
00641         mp.trackAlloc(file,line,mem);
00642         #endif
00643         return mem;
00644     }
00645 };
00646 
00647 //This struct will be the result of an If template if the
00648 //requested size will not fit in a pool.
00649 template<size_t Size>
00650 struct RTAllocHelper
00651 {
00652     inline static void* alloc(const char* file, int line, size_t)
00653     {
00654         void* mem = bigAlloc(Size);
00655         #ifdef LDK_TRACK_ALLOCATION
00656         MemorySingleton::instance().trackAlloc(file,line,mem);
00657         #endif
00658         return mem;
00659     }
00660 };
00661 
00662 /*
00663 ** Normal use API follows
00664 */
00667 
00704 
00705 inline void* bigAlloc(size_t size) //add tracking
00706 {
00707     void* mem = alignedAlloc(size+sizeof(Details::Node));
00708     Details::Node* n = reinterpret_cast<Details::Node*>(mem);
00709     n->mAllocSize = size;
00710     n->mNext = NULL;
00711     n->mHeap = NULL;
00712     #ifndef NDEBUG
00713     n->mThreadID = currentThreadID();
00714     #endif
00715     return (void*)((char*)mem+sizeof(Details::Node));
00716 }
00717 
00718 
00719 
00720 template<size_t Size>
00721 inline void* alloc(const char* file, int line)
00722 {
00723     const int idx =  Details::PoolIdxSearch<Details::NoOfPools::value,Size>::value;
00724     return Meta::If<idx!=-1,CTAllocHelper<idx>, \
00725         RTAllocHelper<Size> >::result::alloc(file,line,Size);
00726 }
00736 #define LDK_CTALLOC(size) LDK::alloc<size>(__FILE__,__LINE__)
00737 
00749 #define LDK_CTTYPEALLOC(type,num) ((type*)LDK::alloc<sizeof(type)*num)>(__FILE__,__LINE__)
00750 
00751 inline void* alloc(const char* file, int line, size_t size)
00752 {
00753     return MemorySingleton::instance().alloc(file,line,size);
00754 }
00764 #define LDK_RTALLOC(size) LDK::alloc(__FILE__,__LINE__,size)
00765 
00777 #define LDK_RTTYPEALLOC(type,num) ((type*)LDK::alloc(__FILE__,__LINE__,sizeof(type)*num))
00778 
00789 inline void dealloc(void* mem)
00790 {
00791     MemorySingleton::instance().dealloc(mem);
00792 }
00793 
00794 inline void* realloc(const char* file, int line, void *mem, size_t newSize)
00795 {
00796     return MemorySingleton::instance().realloc(file,line,mem, newSize);
00797 }
00810 #define LDK_REALLOC(mem, newSize) LDK::realloc(__FILE__,__LINE__,mem,newSize)
00811 
00832 
00833 template <class T>
00834 inline T* create(const char* file, int line)
00835 {
00836     void* mem = LDK::alloc<sizeof(T)>(file,line);
00837     try
00838     {
00839         return new (mem) T();
00840     }
00841     catch(std::exception& e)
00842     {
00843         LDK::dealloc(mem);
00844         throw e;
00845     }
00846     catch(...)
00847     {
00848         LDK::dealloc(mem);
00849         throw;
00850     }
00851 };
00858 #define LDK_CREATE0(Type) LDK::create<Type >(__FILE__,__LINE__)
00859 
00860 
00861 template
00862 <
00863     class T,
00864     typename C1
00865 >
00866 inline T* create(const char* file, int line, C1 c1)
00867 {
00868     void* mem = LDK::alloc<sizeof(T)>(file,line);
00869     try
00870     {
00871         return new (mem) T(c1);
00872     }
00873     catch(std::exception& e)
00874     {
00875         LDK::dealloc(mem);
00876         throw e;
00877     }
00878     catch(...)
00879     {
00880         LDK::dealloc(mem);
00881         throw;
00882     }
00883 };
00890 #define LDK_CREATE1(Type,c1) LDK::create<Type >(__FILE__,__LINE__,c1)
00891 
00892 template
00893 <
00894     class T,
00895     typename C1,
00896     typename C2
00897 >
00898 inline T* create(const char* file, int line, C1 c1, C2 c2)
00899 {
00900     void* mem = LDK::alloc<sizeof(T)>(file,line);
00901     try
00902     {
00903         return new (mem) T(c1,c2);
00904     }
00905     catch(std::exception& e)
00906     {
00907         LDK::dealloc(mem);
00908         throw e;
00909     }
00910     catch(...)
00911     {
00912         LDK::dealloc(mem);
00913         throw;
00914     }
00915 };
00916 
00923 #define LDK_CREATE2(Type,c1,c2) LDK::create<Type >(__FILE__,__LINE__,c1,c2)
00924 
00925 template
00926 <
00927     class T,
00928     typename C1,
00929     typename C2,
00930     typename C3
00931 >
00932 inline T* create(const char* file, int line, C1 c1, C2 c2, C3 c3)
00933 {
00934     void* mem = LDK::alloc<sizeof(T)>(file,line);
00935     try
00936     {
00937         return new (mem) T(c1,c2,c3);
00938     }
00939     catch(std::exception& e)
00940     {
00941         LDK::dealloc(mem);
00942         throw e;
00943     }
00944     catch(...)
00945     {
00946         LDK::dealloc(mem);
00947         throw;
00948     }
00949 };
00950 
00957 #define LDK_CREATE3(Type,c1,c2,c3) LDK::create<Type >(__FILE__,__LINE__,c1,c2,c3)
00958 
00959 template
00960 <
00961     class T,
00962     typename C1,
00963     typename C2,
00964     typename C3,
00965     typename C4
00966 >
00967 inline T* create(const char* file, int line, C1 c1, C2 c2, C3 c3, C4 c4)
00968 {
00969     void* mem = LDK::alloc<sizeof(T)>(file,line);
00970     try
00971     {
00972         return new (mem) T(c1,c2,c3,c4);
00973     }
00974     catch(std::exception& e)
00975     {
00976         LDK::dealloc(mem);
00977         throw e;
00978     }
00979     catch(...)
00980     {
00981         LDK::dealloc(mem);
00982         throw;
00983     }
00984 };
00985 
00992 #define LDK_CREATE4(Type,c1,c2,c3,c4) LDK::create<Type >(__FILE__,__LINE__,c1,c2,c3,c4)
00993 
00994 template
00995 <
00996     class T,
00997     typename C1,
00998     typename C2,
00999     typename C3,
01000     typename C4,
01001     typename C5
01002 >
01003 inline T* create(const char* file, int line, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5)
01004 {
01005     void* mem = LDK::alloc<sizeof(T)>(file,line);
01006     try
01007     {
01008         return new (mem) T(c1,c2,c3,c4,c5);
01009     }
01010     catch(std::exception& e)
01011     {
01012         LDK::dealloc(mem);
01013         throw e;
01014     }
01015     catch(...)
01016     {
01017         LDK::dealloc(mem);
01018         throw;
01019     }
01020 };
01021 
01028 #define LDK_CREATE5(Type,c1,c2,c3,c4,c5) LDK::create<Type >(__FILE__,__LINE__,c1,c2,c3,c4,c5)
01029 
01030 template
01031 <
01032     class T,
01033     typename C1,
01034     typename C2,
01035     typename C3,
01036     typename C4,
01037     typename C5,
01038     typename C6
01039 >
01040 inline T* create(const char* file, int line, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6)
01041 {
01042     void* mem = LDK::alloc<sizeof(T)>(file,line);
01043     try
01044     {
01045         return new (mem) T(c1,c2,c3,c4,c5,c6);
01046     }
01047     catch(std::exception& e)
01048     {
01049         LDK::dealloc(mem);
01050         throw e;
01051     }
01052     catch(...)
01053     {
01054         LDK::dealloc(mem);
01055         throw;
01056     }
01057 };
01058 
01065 #define LDK_CREATE6(Type,c1,c2,c3,c4,c5,c6) LDK::create<Type >(__FILE__,__LINE__,\
01066 c1,c2,c3,c4,c5,c6)
01067 
01068 template
01069 <
01070     class T,
01071     typename C1,
01072     typename C2,
01073     typename C3,
01074     typename C4,
01075     typename C5,
01076     typename C6,
01077     typename C7
01078 >
01079 inline T* create(const char* file, int line, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6, C7 c7)
01080 {
01081     void* mem = LDK::alloc<sizeof(T)>(file,line);
01082     try
01083     {
01084         return new (mem) T(c1,c2,c3,c4,c5,c6,c7);
01085     }
01086     catch(std::exception& e)
01087     {
01088         LDK::dealloc(mem);
01089         throw e;
01090     }
01091     catch(...)
01092     {
01093         LDK::dealloc(mem);
01094         throw;
01095     }
01096 };
01097 
01104 #define LDK_CREATE7(Type,c1,c2,c3,c4,c5,c6,c7) LDK::create<Type >(__FILE__,__LINE__,\
01105 c1,c2,c3,c4,c5,c6,c7)
01106 
01107 template
01108 <
01109     class T,
01110     typename C1,
01111     typename C2,
01112     typename C3,
01113     typename C4,
01114     typename C5,
01115     typename C6,
01116     typename C7,
01117     typename C8
01118 >
01119 inline T* create(const char* file, int line, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6, C7 c7, C8 c8)
01120 {
01121     void* mem = LDK::alloc<sizeof(T)>(file,line);
01122     try
01123     {
01124         return new (mem) T(c1,c2,c3,c4,c5,c6,c7,c8);
01125     }
01126     catch(std::exception& e)
01127     {
01128         LDK::dealloc(mem);
01129         throw e;
01130     }
01131     catch(...)
01132     {
01133         LDK::dealloc(mem);
01134         throw;
01135     }
01136 };
01143 #define LDK_CREATE8(Type,c1,c2,c3,c4,c5,c6,c7,c8) LDK::create<Type >(__FILE__,__LINE__,\
01144 c1,c2,c3,c4,c5,c6,c7,c8)
01145 
01146 template
01147 <
01148     class T,
01149     typename C1,
01150     typename C2,
01151     typename C3,
01152     typename C4,
01153     typename C5,
01154     typename C6,
01155     typename C7,
01156     typename C8,
01157     typename C9
01158 >
01159 inline T* create(const char* file, int line, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6, C7 c7, C8 c8, C9 c9)
01160 {
01161     void* mem = LDK::alloc<sizeof(T)>(file,line);
01162     try
01163     {
01164         return new (mem) T(c1,c2,c3,c4,c5,c6,c7,c8,c9);
01165     }
01166     catch(std::exception& e)
01167     {
01168         LDK::dealloc(mem);
01169         throw e;
01170     }
01171     catch(...)
01172     {
01173         LDK::dealloc(mem);
01174         throw;
01175     }
01176 };
01183 #define LDK_CREATE9(Type,c1,c2,c3,c4,c5,c6,c7,c8,c9) LDK::create<Type >(__FILE__,__LINE__,\
01184 c1,c2,c3,c4,c5,c6,c7,c8,c9)
01185 
01186 template
01187 <
01188     class T,
01189     typename C1,
01190     typename C2,
01191     typename C3,
01192     typename C4,
01193     typename C5,
01194     typename C6,
01195     typename C7,
01196     typename C8,
01197     typename C9,
01198     typename C10
01199 >
01200 inline T* create(const char* file, int line, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6, C7 c7, C8 c8, C9 c9, C10 c10)
01201 {
01202     void* mem = LDK::alloc<sizeof(T)>(file,line);
01203     try
01204     {
01205         return new (mem) T(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10);
01206     }
01207     catch(std::exception& e)
01208     {
01209         LDK::dealloc(mem);
01210         throw e;
01211     }
01212     catch(...)
01213     {
01214         LDK::dealloc(mem);
01215         throw;
01216     }
01217 };
01224 #define LDK_CREATE10(Type,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10) LDK::create<Type >(__FILE__,__LINE__,\
01225 c1,c2,c3,c4,c5,c6,c7,c8,c9,c10)
01226 
01232 template <class T>
01233 inline void destroy(const T* o)
01234 {
01235     //MSVC needs o to be const for SmartPointer :(
01236     T* obj = const_cast<T*>(o);
01237     if(obj)
01238     {
01239         obj->~T();
01240         LDK::dealloc(obj);
01241     }
01242 }
01243 
01250 #define LDK_ALLOCATORS \
01251 inline void* operator new(size_t size)\
01252 {\
01253     return LDK::alloc(size);\
01254 }\
01255 inline void operator delete(void* mem)\
01256 {\
01257     LDK::dealloc(mem);\
01258 }\
01259 inline void* operator new[](size_t size)\
01260 {\
01261     return LDK::alloc(size);\
01262 }\
01263 inline void operator delete[](void* mem)\
01264 {\
01265     LDK::dealloc(mem);\
01266 }
01267 
01269 
01270 }//namespace LDK
01271 
01272 #include "LDK/STLAllocator.h"
01273 #include "LDK/STLMallocAllocator.h"
01274 
01275 //clean up some macros
01276 #undef BYTE_ALIGNMENT
01277 #undef MAX_CHUNKS_PER_HEAP
01278 
01279 #endif //__LDK_MEMORY_HH__

Generated on Fri Aug 17 18:32:26 2007 for LDK by  doxygen 1.5.1