00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdio.h>
00028 #include <cstring>
00029 #include <string.h>
00030 #include <cstdlib>
00031 #include <stdlib.h>
00032 #include <iostream>
00033 #include <ostream>
00034 #include <cassert>
00035 #include "util.h"
00036 #include "mempool.h"
00037
00038 using namespace std;
00039
00046 mempool::mempool(int is, int bs)
00047 {
00048
00049
00050
00051
00052 is=(is>(int)sizeof(char *)?is:0);
00053
00054 is=is + sizeof(char *) - (is % sizeof(char *));
00055
00056 item_size = is;
00057
00058 block_size = bs;
00059
00060 true_size = is * bs;
00061
00062 block_list = new memnode;
00063
00064 block_list->block = new char[true_size];
00065
00066 memset(block_list->block,'0',true_size);
00067
00068 block_list->next = 0;
00069
00070 blocknum = 1;
00071
00072 entries = 0;
00073
00074
00075
00076 char *ptr = free_list = block_list->block;
00077
00078 for (int i=0; i<block_size-1; i++) {
00079 *(char **)ptr= ptr + item_size;
00080 ptr+=item_size;
00081 }
00082 *(char **)ptr = NULL;
00083
00084 }
00085
00086
00087 char * mempool::allocate()
00088 {
00089
00090 char *ptr;
00091
00092 if (free_list==NULL) {
00093 memnode *new_block = new memnode;
00094
00095 new_block->block = new char[true_size];
00096
00097
00098
00099 new_block->next = block_list;
00100
00101 block_list=new_block;
00102
00103
00104
00105 ptr = free_list = block_list->block;
00106
00107 for (int i=0; i<block_size-1; i++) {
00108 *(char **)ptr = ptr + item_size;
00109 ptr = ptr + item_size;
00110 }
00111
00112 *(char **)ptr=NULL;
00113
00114 blocknum++;
00115 }
00116
00117 assert(free_list);
00118
00119 ptr = free_list;
00120
00121 free_list=*(char **)ptr;
00122
00123 *(char **)ptr=NULL;
00124
00125 entries++;
00126
00127 return ptr;
00128
00129 }
00130
00131
00132 int mempool::free(char* addr)
00133 {
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 *(char **)addr=free_list;
00151 free_list=addr;
00152
00153 entries--;
00154
00155 return 1;
00156 }
00157
00158
00159 mempool::~mempool()
00160 {
00161 memnode *ptr;
00162
00163 while (block_list !=NULL) {
00164 ptr=block_list->next;
00165 delete [] block_list->block;
00166 delete block_list;
00167 block_list=ptr;
00168 }
00169
00170 }
00171
00172 void mempool::map (ostream& co)
00173 {
00174
00175 co << "mempool memory map:\n";
00176
00177
00178 memnode *bl=block_list;
00179 char *fl=free_list;
00180
00181 char* img=new char[block_size+1];
00182 img[block_size]='\0';
00183
00184 while (bl !=NULL) {
00185
00186 memset(img,'#',block_size);
00187
00188 fl=free_list;
00189 while (fl != NULL) {
00190 if ((fl >= bl->block)
00191 &&
00192 (fl < bl->block + true_size)) {
00193 img[(fl-bl->block)/item_size]='-';
00194 }
00195
00196 fl=*(char **)fl;
00197 }
00198
00199 co << img << "\n";
00200 bl=bl->next;
00201 }
00202 delete [] img;
00203 }
00204
00205 void mempool::stat()
00206 {
00207
00208 VERBOSE(1, "mempool class statistics\n"
00209 << "entries " << entries
00210 << " blocks " << blocknum
00211 << " used memory " << (blocknum * true_size)/1024 << " Kb\n");
00212 }
00213
00214
00215
00216 strstack::strstack(int bs)
00217 {
00218
00219 size=bs;
00220 list=new memnode;
00221
00222 list->block=new char[size];
00223
00224 list->next=0;
00225
00226 memset(list->block,'\0',size);
00227 idx=0;
00228
00229 waste=0;
00230 memory=size;
00231 entries=0;
00232 blocknum=1;
00233
00234 }
00235
00236
00237 void strstack::stat()
00238 {
00239
00240 VERBOSE(1, "strstack class statistics\n"
00241 << "entries " << entries
00242 << " blocks " << blocknum
00243 << " used memory " << memory/1024 << " Kb\n");
00244 }
00245
00246
00247 const char *strstack::push(const char *s)
00248 {
00249 int len=strlen(s);
00250
00251 if ((len+1) >= size) {
00252 cerr << "strstack::push string is too long\n";
00253 exit(1);
00254 };
00255
00256 if ((idx+len+1) >= size) {
00257
00258
00259
00260
00261
00262 waste+=size-idx;
00263 blocknum++;
00264 memory+=size;
00265
00266 memnode* nd=new memnode;
00267 nd->block=new char[size];
00268 nd->next=list;
00269
00270 list=nd;
00271
00272 memset(list->block,'\0',size);
00273
00274 idx=0;
00275
00276 }
00277
00278
00279
00280 strcpy(&list->block[idx],s);
00281
00282 idx+=len+1;
00283
00284 entries++;
00285
00286 return &list->block[idx-len-1];
00287
00288 }
00289
00290
00291 const char *strstack::pop()
00292 {
00293
00294 if (list==0) return 0;
00295
00296 if (idx==0) {
00297
00298
00299
00300 memnode *ptr=list->next;
00301
00302 delete [] list->block;
00303 delete list;
00304
00305 list=ptr;
00306
00307 if (list==0)
00308 return 0;
00309 else
00310 idx=size-1;
00311 }
00312
00313
00314 while (idx>0)
00315 if (list->block[idx--]!='\0')
00316 break;
00317
00318
00319 while (idx>0)
00320 if (list->block[idx--]=='\0')
00321 break;
00322
00323 entries--;
00324
00325 if (list->block[idx+1]=='\0') {
00326 idx+=2;
00327 memset(&list->block[idx],'\0',size-idx);
00328 return &list->block[idx];
00329 } else {
00330 idx=0;
00331 memset(&list->block[idx],'\0',size);
00332 return &list->block[0];
00333 }
00334 }
00335
00336
00337 const char *strstack::top()
00338 {
00339
00340 int tidx=idx;
00341 memnode *tlist=list;
00342
00343 if (tlist==0) return 0;
00344
00345 if (idx==0) {
00346
00347 tlist=tlist->next;
00348
00349 if (tlist==0) return 0;
00350
00351 tidx=size-1;
00352 }
00353
00354
00355 while (tidx>0)
00356 if (tlist->block[tidx--]!='\0')
00357 break;
00358
00359
00360
00361
00362 while (tidx>0)
00363 if (tlist->block[tidx--]=='\0')
00364 break;
00365
00366 if (tlist->block[tidx+1]=='\0') {
00367 tidx+=2;
00368 return &tlist->block[tidx];
00369 } else {
00370 tidx=0;
00371 return &tlist->block[0];
00372 }
00373
00374 }
00375
00376
00377 strstack::~strstack()
00378 {
00379 memnode *ptr;
00380 while (list !=NULL) {
00381 ptr=list->next;
00382 delete [] list->block;
00383 delete list;
00384 list=ptr;
00385 }
00386 }
00387
00388
00389 storage::storage(int maxsize,int blocksize)
00390 {
00391 newmemory=0;
00392 newcalls=0;
00393 setsize=maxsize;
00394 poolsize=blocksize;
00395 poolset=new mempool* [setsize+1];
00396 for (int i=0; i<=setsize; i++)
00397 poolset[i]=NULL;
00398 }
00399
00400
00401 storage::~storage()
00402 {
00403 for (int i=0; i<=setsize; i++)
00404 if (poolset[i])
00405 delete poolset[i];
00406 delete [] poolset;
00407 }
00408
00409 char *storage::allocate(int size)
00410 {
00411
00412 if (size<=setsize) {
00413 if (!poolset[size]) {
00414 poolset[size]=new mempool(size,poolsize/size);
00415 }
00416 return poolset[size]->allocate();
00417 } else {
00418
00419 newmemory+=size+8;
00420 newcalls++;
00421 char* p=(char *)calloc(sizeof(char),size);
00422 if (p==NULL) {
00423 cerr << "storage::alloc insufficient memory\n";
00424 exit(1);
00425 }
00426 return p;
00427 }
00428 }
00429
00430 char *storage::reallocate(char *oldptr,int oldsize,int newsize)
00431 {
00432
00433 char *newptr;
00434
00435 assert(newsize>oldsize);
00436
00437 if (oldsize<=setsize) {
00438 if (newsize<=setsize) {
00439 if (!poolset[newsize])
00440 poolset[newsize]=new mempool(newsize,poolsize/newsize);
00441 newptr=poolset[newsize]->allocate();
00442 memset((char*)newptr,0,newsize);
00443 } else
00444 newptr=(char *)calloc(sizeof(char),newsize);
00445
00446 if (oldptr && oldsize) {
00447 memcpy(newptr,oldptr,oldsize);
00448 poolset[oldsize]->free(oldptr);
00449 }
00450 } else {
00451 newptr=(char *)realloc(oldptr,newsize);
00452 if (newptr==oldptr)
00453 cerr << "r\b";
00454 else
00455 cerr << "a\b";
00456 }
00457 if (newptr==NULL) {
00458 cerr << "storage::realloc insufficient memory\n";
00459 exit(1);
00460 }
00461
00462 return newptr;
00463 }
00464
00465 int storage::free(char *addr,int size)
00466 {
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 if (size>setsize)
00477 return free(addr),1;
00478 else {
00479 poolset[size] && poolset[size]->free(addr);
00480 }
00481 return 1;
00482 }
00483
00484
00485 void storage::stat()
00486 {
00487 int used=0;
00488 int memory=sizeof(char *) * setsize;
00489 int waste=0;
00490
00491 for (int i=0; i<=setsize; i++)
00492 if (poolset[i]) {
00493 used++;
00494 memory+=poolset[i]->used();
00495 waste+=poolset[i]->wasted();
00496 }
00497
00498 VERBOSE(1, "storage class statistics\n"
00499 << "alloc entries " << newcalls
00500 << " used memory " << newmemory/1024 << "Kb\n"
00501 << "mpools " << setsize
00502 << " active " << used
00503 << " used memory " << memory/1024 << "Kb"
00504 << " wasted " << waste/1024 << "Kb\n");
00505 }
00506