1 // Emacs style mode select -*- C++ -*- 2 //----------------------------------------------------------------------------- 3 // 4 // $Id: m_random.h 3799 2013-04-24 03:12:44Z mike $ 5 // 6 // Copyright (C) 1993-1996 by id Software, Inc. 7 // Copyright (C) 2006-2014 by The Odamex Team. 8 // 9 // This program is free software; you can redistribute it and/or 10 // modify it under the terms of the GNU General Public License 11 // as published by the Free Software Foundation; either version 2 12 // of the License, or (at your option) any later version. 13 // 14 // This program is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // DESCRIPTION: 20 // Memory pool allocation 21 // Allocates a large pool of memory and allocates blocks of it when asked. 22 // Memory can only be freed by the clear() function for simplicity. If 23 // the intial memory pool is exhausted, additional pools are allocated. These 24 // are consolodated into one large pool the next time clear() is called. 25 // 26 //----------------------------------------------------------------------------- 27 28 29 #ifndef __M_MEMPOOL__ 30 #define __M_MEMPOOL__ 31 32 #include "doomtype.h" 33 #include <cstring> 34 35 class MemoryPool 36 { 37 public: MemoryPool(size_t initial_size)38 MemoryPool(size_t initial_size) : 39 num_blocks(0), block_size(NULL), data_block(NULL), free_block(NULL) 40 { 41 resize(initial_size); 42 } 43 ~MemoryPool()44 ~MemoryPool() 45 { 46 free_data(); 47 } 48 clear()49 void clear() 50 { 51 if (num_blocks <= 1) 52 { 53 free_block = data_block[0]; 54 return; 55 } 56 57 size_t new_size = 0; 58 if (block_size != NULL) 59 new_size = block_size[num_blocks - 1]; 60 free_data(); 61 resize(new_size); 62 } 63 64 template<typename T> alloc(size_t count)65 T* alloc(size_t count) 66 { 67 while (free_block + count * sizeof(T) > 68 data_block[num_blocks - 1] + block_size[num_blocks - 1]) 69 resize(2 * block_size[num_blocks - 1]); 70 71 T* ptr = reinterpret_cast<T*>(free_block); 72 free_block += count * sizeof(T); 73 return ptr; 74 } 75 76 private: resize(size_t new_size)77 void resize(size_t new_size) 78 { 79 if (new_size == 0) 80 return; 81 82 num_blocks++; 83 84 size_t* new_block_size = new size_t[num_blocks]; 85 if (block_size != NULL) 86 { 87 memcpy(new_block_size, block_size, (num_blocks - 1) * sizeof(size_t)); 88 delete [] block_size; 89 } 90 new_block_size[num_blocks - 1] = new_size; 91 block_size = new_block_size; 92 93 byte** new_data_block = new byte*[num_blocks]; 94 if (data_block != NULL) 95 { 96 memcpy(new_data_block, data_block, (num_blocks - 1) * sizeof(byte*)); 97 delete [] data_block; 98 } 99 new_data_block[num_blocks - 1] = new byte[new_size]; 100 data_block = new_data_block; 101 102 free_block = data_block[num_blocks - 1]; 103 } 104 free_data()105 void free_data() 106 { 107 for (size_t i = 0; i < num_blocks; i++) 108 delete [] data_block[i]; 109 110 delete [] block_size; 111 delete [] data_block; 112 num_blocks = 0; 113 block_size = NULL; 114 data_block = NULL; 115 free_block = NULL; 116 } 117 118 size_t num_blocks; 119 size_t* block_size; 120 byte** data_block; 121 byte* free_block; 122 }; 123 124 #endif // __M_MEMPOOL__ 125