glmemorypool.h

00001 /*
00002 Copyright (c) 2000-2003 Lee Thomason (www.grinninglizard.com)
00003 Grinning Lizard Utilities.
00004 
00005 This software is provided 'as-is', without any express or implied 
00006 warranty. In no event will the authors be held liable for any 
00007 damages arising from the use of this software.
00008 
00009 Permission is granted to anyone to use this software for any 
00010 purpose, including commercial applications, and to alter it and 
00011 redistribute it freely, subject to the following restrictions:
00012 
00013 1. The origin of this software must not be misrepresented; you must 
00014 not claim that you wrote the original software. If you use this 
00015 software in a product, an acknowledgment in the product documentation 
00016 would be appreciated but is not required.
00017 
00018 2. Altered source versions must be plainly marked as such, and 
00019 must not be misrepresented as being the original software.
00020 
00021 3. This notice may not be removed or altered from any source 
00022 distribution.
00023 */
00024 
00025 
00026 #ifndef GRINLIZ_MEMORY_POOL
00027 #define GRINLIZ_MEMORY_POOL
00028 
00029 #include "gldebug.h"
00030 
00031 #ifdef DEBUG
00032 #include <string.h>
00033 #endif
00034 
00035 
00036 namespace grinliz {
00037 
00038 /*      A memory pool that will dynamically grow as memory is needed.
00039 */
00040 class MemoryPool
00041 {
00042   public:
00043         MemoryPool( const char* _name, unsigned objectSize, unsigned blockSize = 4096 );
00044         ~MemoryPool();
00045 
00046         void* Alloc() {
00047                 void* ret = 0;
00048 
00049                 if ( !head ) {
00050                         NewBlock();
00051                         GLASSERT( head );
00052                 }
00053 
00054                 ret = head;
00055                 head = head->nextChunk;
00056 
00057                 ++numChunks;
00058                 #ifdef DEBUG
00059                         memset( ret, 0xaa, chunkSize );
00060                 #endif
00061 
00062                 return ret;
00063         }
00064 
00065         void Free( void* mem ) {
00066                 if ( !mem )
00067                         return;
00068 
00069                 Chunk* chunk = (Chunk*) mem;
00070 
00071                 --numChunks;
00072                 #ifdef DEBUG
00073                         memset( mem, 0xbb, chunkSize );
00074                 #endif
00075 
00076                 chunk->nextChunk = head;
00077                 head = chunk;
00078         }
00079 
00080         void FreePool();
00081 
00082         unsigned Blocks()       { return numBlocks; }
00083         unsigned Chunks()       { return numChunks; }
00084         unsigned MemoryUsed()   { return numBlocks * blockSize; }
00085 
00086   private:
00087         struct Chunk
00088         {
00089                 Chunk* nextChunk;
00090         };
00091 
00092         struct Block
00093         {
00094                 Block* nextBlock;
00095                 Chunk* chunk;           // treated as an array of chunks.
00096         };
00097 
00098         void NewBlock();
00099 
00100         unsigned chunkSize;                     // size of chunk in bytes
00101         unsigned blockSize;                     // size of block in bytes
00102         unsigned chunksPerBlock;
00103         
00104         unsigned numBlocks;
00105         unsigned numChunks;
00106         
00107         Block* rootBlock;
00108         Chunk* head;
00109 
00110         const char* name;
00111 };
00112 
00113 /*      A memory pool that has a fixed allocation.
00114         Essentially a cross between a linked list and an array.
00115 */
00116 template < class T, int COUNT >
00117 class FixedMemoryPool
00118 {
00119   private:
00120         struct Chunk
00121         {
00122                 Chunk* next;
00123         };
00124 
00125   public:
00126         FixedMemoryPool()
00127         {
00128                 GLASSERT( sizeof( T ) >= sizeof( Chunk* ) );
00129                 for( int i=0; i<COUNT-1; ++i )
00130                 {
00131                         ( (Chunk*)(&memory[i]) )->next = (Chunk*)(&memory[i+1]);
00132                 }
00133                 ( (Chunk*)(&memory[COUNT-1]) )->next = 0;
00134                 root = ( (Chunk*)(&memory[0]) );
00135                 inUse = 0;
00136         }
00137 
00138         ~FixedMemoryPool()      {}
00139 
00140         T* Alloc()
00141         {
00142                 T* ret = 0;
00143                 if ( root )
00144                 {
00145                         ret = (T*) root;
00146                         root = root->next;
00147                         ++inUse;
00148                 }
00149                 return ret;
00150         }
00151 
00152         void Free( T* _mem )
00153         {
00154                 if ( _mem )
00155                 {
00156                         Chunk* mem = (Chunk*) _mem;
00157                         #ifdef DEBUG
00158                                 memset( mem, 0xfe, sizeof( T ) );
00159                         #endif
00160                         mem->next = root;
00161                         root = mem;
00162                         --inUse;
00163                 }
00164         }
00165 
00166         unsigned InUse()        {       return inUse; }
00167         unsigned Remain()       {       return COUNT - inUse; }
00168         bool     Contains( T* mem )     { return mem >= memory && mem < &memory[COUNT]; }
00169 
00170   private:
00171         T memory[ COUNT ];
00172         unsigned inUse;
00173         Chunk* root;
00174 };
00175 
00176 
00177 /*      This is memory allocation for when you know exactly how much 
00178         memory is going to be needed. So it's a way to pre-allocate 
00179         while still using the new and delete operators.
00180 
00181         FIXME 16 byte align
00182 */
00183 class LinearMemoryPool
00184 {
00185   public:
00187         LinearMemoryPool( unsigned totalMemory );
00188         ~LinearMemoryPool();
00189 
00191         void* Alloc( unsigned allocate );
00192 
00195         void Free( void* )              {}
00196 
00198         bool OutOfMemory()                      { return current == end; }
00199 
00200   public:
00201         char*   base;
00202         char*   current;
00203         char*   end;
00204 };
00205 
00206 };
00207 
00208 #endif

Generated on Thu Jul 20 20:45:31 2006 for Kyra by  doxygen 1.4.7