- Main Page
- Classes
- Files
- Directories
- Related Pages

# 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