00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _MEM_POOL_H_
00023 #define _MEM_POOL_H_
00024
00025 #include "basictypes.h"
00026 #include <cassert>
00027 #include <stdexcept>
00028 #include <stdlib.h>
00029 #include <new>
00030 #include <iostream>
00031
00032
00033
00034
00035
00036
00037 template<class T>
00038 class MemoryPooled
00039 {
00040 public:
00041 MemoryPooled() {}
00042 ~MemoryPooled() {}
00043
00044 static void* operator new(size_t size);
00045 static void operator delete(void *dead, size_t size);
00046
00047 static int FreeBlocks();
00048
00049 protected:
00050 union {
00051 T data;
00052 MemoryPooled<T> *next;
00053 };
00054
00055 private:
00056
00057 static const int BLOCK_SIZE;
00058 static MemoryPooled<T>* allocate_block();
00059 static MemoryPooled<T> *freelist;
00060 };
00061
00062
00063 template<class T>
00064 void* MemoryPooled<T> :: operator new(size_t size) {
00065
00066 if( size != sizeof(MemoryPooled<T>)) {
00067 cerr << "mempool: allocated object of nonstandard size" << endl;
00068 return ::operator new(size);
00069 }
00070 MemoryPooled<T> *p = freelist;
00071 if(p) {
00072 freelist = p->next;
00073 } else {
00074 assert(BLOCK_SIZE > 1);
00075 p = allocate_block();
00076 freelist = p->next;
00077 assert(freelist);
00078 }
00079 assert(p);
00080 return p;
00081 }
00082
00083
00084 template<class T>
00085 MemoryPooled<T>* MemoryPooled<T> :: allocate_block() {
00086 MemoryPooled<T> *newBlock =
00087 static_cast<MemoryPooled<T>*>(::operator new(BLOCK_SIZE *
00088 sizeof(MemoryPooled<T>)));
00089
00090 memset(newBlock,0,BLOCK_SIZE * sizeof(MemoryPooled<T>));
00091 for(int i = 0; i < BLOCK_SIZE - 1; i++) {
00092 newBlock[i].next = &newBlock[i+1];
00093 }
00094 newBlock[BLOCK_SIZE - 1].next = 0;
00095 return newBlock;
00096 }
00097
00098
00099 template<class T>
00100 void MemoryPooled<T> :: operator delete(void *dead, size_t size) {
00101
00102 if( dead == 0 ) {
00103 return;
00104 }
00105 if( size != sizeof(MemoryPooled<T>) ) {
00106 cerr << "warning: overloaded delete called global delete" << endl;
00107 :: operator delete(dead);
00108 return;
00109 }
00110 MemoryPooled<T> *shell = static_cast<MemoryPooled<T>*>(dead);
00111 shell->next = freelist;
00112 freelist = shell;
00113 }
00114
00115
00116 template<class T>
00117 int MemoryPooled<T> :: FreeBlocks() {
00118
00119 MemoryPooled<T> *p = freelist;
00120 int fsize = 0;
00121 while( p ) {
00122 fsize += sizeof(MemoryPooled<T>);
00123 p = p->next;
00124 }
00125 return fsize;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 template<class S>
00141 union MemPoolObject {
00142 S data;
00143 MemPoolObject<S>* admin_next;
00144 int admin_length;
00145 };
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 template<class S>
00159 class MemPool
00160 {
00161
00162 public:
00163 MemPool() {}
00164 ~MemPool() {}
00165
00166 MemPoolObject<S>* Allocate(int numels) throw (range_error);
00167 void Deallocate(MemPoolObject<S>* dead, int numels);
00168
00169 static int FreeBlocks1();
00170 static int FreeBlocks2();
00171 private:
00172
00173 static const int BLOCK_SIZE;
00174 static MemPoolObject<S>* allocate_block1();
00175 static MemPoolObject<S>* allocate_block2();
00176
00177 static MemPoolObject<S> *mempool1;
00178 static MemPoolObject<S> *mempool2;
00179 };
00180
00181 template<class S>
00182 MemPoolObject<S>* MemPool<S> :: Allocate(int numels) throw (range_error) {
00183 if( (numels <= 0) ) {
00184 cerr << "warning: overloaded new[] called global new" << endl;;
00185 return static_cast<MemPoolObject<S>*>(::operator new[](numels * sizeof(MemPoolObject<S>)));
00186 } else if( numels == 1 ) {
00187
00188 MemPoolObject<S> *p = mempool1;
00189 if(p) {
00190 mempool1 = p[0].admin_next;
00191 } else {
00192 p = allocate_block1();
00193 assert(p);
00194 mempool1 = p[0].admin_next;
00195 }
00196 return p;
00197 }
00198
00199
00200
00201 MemPoolObject<S> *p = mempool2;
00202 if(p) {
00203
00204 MemPoolObject<S> *prev = NULL;
00205 while( p && (p[1].admin_length < numels) ) {
00206 prev = p;
00207 p = p[0].admin_next;
00208 }
00209 if( p ) {
00210
00211 if( prev ) {
00212 prev[0].admin_next = p[0].admin_next;
00213 } else {
00214 mempool2 = p[0].admin_next;
00215 }
00216
00217
00218
00219 int remaining = p[1].admin_length - numels;
00220 if( remaining == 1 ) {
00221
00222 p[numels].admin_next = mempool1;
00223 mempool1 = &p[numels];
00224 } else if( remaining > 1 ) {
00225 p[numels].admin_next = mempool2;
00226 p[numels + 1].admin_length = remaining;
00227 mempool2 = &p[numels];
00228 }
00229
00230 return p;
00231 }
00232 }
00233
00234
00235 assert(BLOCK_SIZE > 1);
00236 if(numels > BLOCK_SIZE) {
00237 cerr << "BLOCK_SIZE is too small" << endl;
00238 throw range_error("");
00239 } else {
00240 p = allocate_block2();
00241
00242 int remaining = BLOCK_SIZE - numels;
00243 if( remaining == 1 ) {
00244 p[numels].admin_next = mempool1;
00245 mempool1 = &p[numels];
00246 } else if( remaining > 1 ) {
00247 p[numels].admin_next = mempool2;
00248 p[numels + 1].admin_length = remaining;
00249 mempool2 = &p[numels];
00250 }
00251 return p;
00252 }
00253 }
00254
00255 template<class S>
00256 MemPoolObject<S>* MemPool<S> :: allocate_block1() {
00257 MemPoolObject<S> *newBlock =
00258 static_cast<MemPoolObject<S>*>(::operator new(BLOCK_SIZE * sizeof(MemPoolObject<S>)));
00259
00260 memset(newBlock,0,BLOCK_SIZE * sizeof(MemPoolObject<S>));
00261 for(int i = 0; i < BLOCK_SIZE - 1; i++) {
00262 newBlock[i].admin_next = &newBlock[i+1];
00263 }
00264 newBlock[BLOCK_SIZE - 1].admin_next = 0;
00265 return newBlock;
00266 }
00267
00268 template<class S>
00269 MemPoolObject<S>* MemPool<S> :: allocate_block2() {
00270 MemPoolObject<S> *newBlock =
00271 static_cast<MemPoolObject<S>*>(::operator new(BLOCK_SIZE * sizeof(MemPoolObject<S>)));
00272 memset(newBlock,0,BLOCK_SIZE * sizeof(MemPoolObject<S>));
00273 newBlock[0].admin_next = 0;
00274 newBlock[1].admin_length = BLOCK_SIZE;
00275 return newBlock;
00276 }
00277
00278 template<class S>
00279 int MemPool<S> :: FreeBlocks1() {
00280 MemPoolObject<S> *p = mempool1;
00281 int fsize = 0;
00282 while( p ) {
00283 fsize += sizeof(MemPoolObject<S>);
00284 p = p[0].admin_next;
00285 }
00286 return fsize;
00287 }
00288
00289 template<class S>
00290 int MemPool<S> :: FreeBlocks2() {
00291 MemPoolObject<S> *p = mempool2;
00292 int fsize = 0;
00293 while( p ) {
00294 fsize += p[1].admin_length * sizeof(MemPoolObject<S>);
00295 p = p[0].admin_next;
00296 }
00297 return fsize;
00298 }
00299
00300 template<class S>
00301 void MemPool<S> :: Deallocate(MemPoolObject<S> *dead, int numels) {
00302 if( numels == 1 ) {
00303 dead[0].admin_next = mempool1;
00304 mempool1 = dead;
00305 } else if( numels > 1 ) {
00306
00307 dead[1].admin_length = numels;
00308 dead[0].admin_next = mempool2;
00309 mempool2 = dead;
00310 }
00311 }
00312
00313 #endif