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
00028
00029 #ifndef NO_MALLOC_REPLACEMENT
00030 #define NO_MALLOC_REPLACEMENT
00031 #endif
00032
00033 #include "defs.h"
00034
00035 #include <iostream>
00036 #include <sstream>
00037 #include <stdio.h>
00038 #include "tMemManager.h"
00039 #include "tError.h"
00040
00041 #ifdef HAVE_STDLIB_H
00042 #include <stdlib.h>
00043 #endif
00044
00045 #ifdef WIN32
00046 #ifdef _MSC_VER
00047 #include <windows.h>
00048 #include <winuser.h>
00049 #ifdef _DEBUG
00050 #undef _DEBUG
00051 #endif
00052 #include <CrtDbg.h>
00053 #pragma warning (disable : 4073)
00054 #pragma init_seg(lib)
00055 #endif
00056 #ifdef __MINGW32__
00057 #include <windows.h>
00058 #include <winuser.h>
00059 #ifdef _DEBUG
00060 #undef _DEBUG
00061 #endif
00062 #endif
00063 static CRITICAL_SECTION mutex;
00064 #endif
00065
00066 #ifndef DONTUSEMEMMANAGER
00067 #define NEW
00068 #endif
00069
00070 #ifdef DEBUG
00071 #define LEAKFINDER
00072
00073
00074 #ifdef LEAKFINDER
00075 #define PROFILER
00076 #endif
00077
00078 #ifdef WIN32
00079
00080
00081
00082 #endif
00083
00084
00085
00086
00087 #endif
00088
00089 static bool reported=false;
00090
00091 #ifdef HAVE_LIBZTHREAD
00092 #include <zthread/FastRecursiveMutex.h>
00093
00094 static ZThread::FastRecursiveMutex st_mutex;
00095 #else
00096 class tMockMutex
00097 {
00098 public:
00099 void acquire(){};
00100 void release(){};
00101 };
00102
00103 static tMockMutex st_mutex;
00104 #endif
00105
00106 class tBottleNeck
00107 {
00108 public:
00109 tBottleNeck()
00110 {
00111 st_mutex.acquire();
00112 }
00113
00114 ~tBottleNeck()
00115 {
00116 st_mutex.release();
00117 }
00118 };
00119
00120
00121 #ifndef HAVE_WMEMSET
00122 static inline wchar_t *wmemset(wchar_t *wcs, wchar_t wc, size_t n) throw()
00123 {
00124
00125 for( size_t i = 0; i < n; ++i )
00126 {
00127 wcs[i] = wc;
00128 }
00129
00130 return wcs;
00131 }
00132 #endif
00133
00134 void leak(){
00135 if (!reported)
00136 {
00137 reported=true;
00138 #ifdef DEBUG
00139 #ifdef WIN32
00140 MessageBox (NULL, "Memory leak detected!" , "Memory Leak", MB_OK);
00141 #else
00142 std::cerr << "\n\nMemory leak detected!\n\n";
00143 #endif
00144 #endif
00145 tMemManBase::Profile();
00146 }
00147 }
00148
00149
00150
00151 #include "tList.h"
00152
00153 class memblock;
00154
00155 #ifdef DEBUG
00156 #define SAFETYBYTES 16
00157 #else
00158 #define SAFETYBYTES 0
00159 #endif
00160 #define PAD 197
00161
00162
00163 struct tAllocationInfo
00164 {
00165 #ifdef LEAKFINDER
00166 const char *filename;
00167 const char *classname;
00168 int checksum;
00169 int line;
00170 bool array;
00171 #endif
00172
00173 tAllocationInfo( bool
00174 #ifdef LEAKFINDER
00175 array_
00176 #endif
00177 )
00178 #ifdef LEAKFINDER
00179 : filename( "XXX" ), classname( "XXX" ), checksum(-1), line(0), array( array_ )
00180 #endif
00181 {
00182 }
00183 };
00184
00185 class tMemMan: public tMemManBase
00186 {
00187 public:
00188 static void *Alloc(tAllocationInfo const & info, size_t s);
00189 static void Dispose(tAllocationInfo const & info, void *p);
00190 static void DisposeButKeep(tAllocationInfo const & info, void *p);
00191 };
00192
00193
00194 class tMemManager{
00195 friend class memblock;
00196 public:
00197 tMemManager(int size, int blocksize);
00198 tMemManager(int size);
00199 ~tMemManager();
00200
00201 void * Alloc( tAllocationInfo const & info );
00202 static void * AllocDefault(tAllocationInfo const & info, size_t size);
00203 static void Dispose(tAllocationInfo const & info, void *p, bool keep=false);
00204 void complete_Dispose(memblock *m);
00205 void Check();
00206
00207 private:
00208 int Lower(int i){
00209 if(i%2==0)
00210 return i/2-1;
00211 else
00212 return (i-1)/2;
00213 }
00214
00215 bool SwapIf(int i,int j);
00216
00217
00218
00219 void SwapDown(int j);
00220 void SwapUp(int i);
00221
00222
00223 void CheckHeap();
00224
00225
00226 static int UpperL(int i){return 2*i+1;}
00227 static int UpperR(int i){return 2*i+2;}
00228
00229 void Insert(memblock *b);
00230 void Remove(memblock *b);
00231 memblock * Remove(int i);
00232 void Replace(int i);
00233
00234 void Replace(memblock *e);
00235
00236
00237 int size;
00238 int blocksize;
00239
00240 tList<memblock, true> blocks;
00241 tList<memblock, true> full_blocks;
00242
00243 int semaphore;
00244 };
00245
00246 static bool inited=false;
00247
00248 #ifdef LEAKFINDER
00249 #include <fstream>
00250 #define MAXCHECKSUM 100001
00251 static int counter[MAXCHECKSUM];
00252 static int leaks[MAXCHECKSUM];
00253 #ifdef PROFILER
00254 static const char *checksum_filename[MAXCHECKSUM];
00255 static const char *checksum_classname[MAXCHECKSUM];
00256 static int checksum_line[MAXCHECKSUM];
00257 static int checksum_blocks[MAXCHECKSUM];
00258 static int checksum_bytes[MAXCHECKSUM];
00259 #endif
00260
00261
00262 static char const *leakname="leak.log";
00263 static bool checkleaks=true;
00264 #endif
00265
00266 void begin_checkleaks(){
00267 #ifdef LEAKFINDER
00268 checkleaks=true;
00269 #endif
00270 }
00271
00272 struct chunkinfo{
00273 unsigned char pos:8;
00274 unsigned char occupied:1;
00275 unsigned char size_in_dwords:7;
00276 unsigned char next:8;
00277 unsigned char prev:8;
00278 #ifdef LEAKFINDER
00279 int checksum;
00280 int counter;
00281 bool array;
00282 #endif
00283 #ifdef PROFILER
00284 size_t realSize;
00285 #endif
00286 };
00287
00288
00289
00290 class memblock{
00291 public:
00292
00293 int value;
00294
00295 int hID;
00296
00297 tMemManager *myman;
00298
00299 int size;
00300 unsigned char first_free;
00301
00302
00303 ~memblock(){
00304 if (myman) myman->blocks.Remove(this,hID);
00305
00306 }
00307
00308 chunkinfo & chunk(int i){
00309 tASSERT(i>=0 && i<myman->blocksize);
00310 return *(
00311 (chunkinfo *)(void *)
00312 ( ( (char *)(this+1) )+(sizeof(chunkinfo)+size+SAFETYBYTES)*i)
00313 );
00314 }
00315
00316 char * safety(int i){
00317 tASSERT(i>=0 && i<myman->blocksize);
00318 return (
00319 ( ( (char *)(this+1) )+(sizeof(chunkinfo)+size+SAFETYBYTES)*i)
00320 +sizeof(chunkinfo)+size );
00321 }
00322
00323 void * data(int i){
00324 tASSERT(i>=0 && i<myman->blocksize);
00325 return (void *)
00326 ( ( (char *)(this+1) )+(sizeof(chunkinfo)+size+SAFETYBYTES)*i + sizeof(chunkinfo));
00327 }
00328
00329
00330 memblock(tMemManager *man):value(man->blocksize),hID(-1),myman(man){
00331
00332 size=man->size;
00333 myman->blocks.Add(this,hID);
00334
00335
00336
00337 for (int i=man->blocksize-1 ; i>=0 ; i--){
00338 if (i<man->blocksize-1)
00339 chunk(i).next=i+2;
00340 else
00341 chunk(i).next=0;
00342
00343 if (i>0)
00344 chunk(i).prev=i;
00345 else
00346 chunk(i).prev=0;
00347
00348 chunk(i).pos = i;
00349 chunk(i).occupied = false;
00350 chunk(i).size_in_dwords = size >> 2;
00351
00352 for (int j=SAFETYBYTES-1;j>=0;j--)
00353 safety(i)[j]=(j ^ PAD);
00354 }
00355
00356 #ifdef MEM_DEB
00357 Check();
00358 #endif
00359
00360 first_free=1;
00361 }
00362
00363
00364 void *Alloc( tAllocationInfo const & info ){
00365 #ifdef MEM_DEB_SMALL
00366 Check();
00367 #endif
00368
00369
00370 tASSERT(value>0);
00371 value--;
00372
00373
00374
00375 int ret=-1;
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 ret=first_free-1;
00387 tASSERT(ret>=0);
00388
00389
00390 chunk(ret).occupied=true;
00391 first_free=chunk(ret).next;
00392
00393 if (first_free>0) chunk(first_free-1).prev=0;
00394
00395 chunk(ret).next=chunk(ret).prev=0;
00396
00397
00398 #ifdef LEAKFINDER
00399 if (info.checksum >= 0){
00400 tASSERT(info.checksum < MAXCHECKSUM);
00401
00402 #ifdef PROFILER
00403 if (!counter[info.checksum]){
00404 checksum_filename [info.checksum] = info.filename;
00405 checksum_classname[info.checksum] = info.classname;
00406 checksum_line [info.checksum] = info.line;
00407 }
00408 checksum_blocks[info.checksum]++;
00409 checksum_bytes[info.checksum]+=size;
00410 chunk(ret).realSize = size;
00411 #endif
00412 chunk(ret).array=info.array;
00413 chunk(ret).checksum=info.checksum;
00414 chunk(ret).counter =++counter[info.checksum];
00415
00416 static int count =0;
00417 if (checkleaks && counter[info.checksum] == leaks[info.checksum]){
00418 count ++;
00419 if (count <= 0)
00420 {
00421 std::cerr << "one of the endless ignored objects that were leaky last time created!\n";
00422 }
00423 else if (count <= 1)
00424 {
00425 std::cerr << "Object that was leaky last time created!\n";
00426 st_Breakpoint();
00427 }
00428 else if (count <= 3)
00429 {
00430 std::cerr << "One more object that was leaky last time created!\n";
00431 st_Breakpoint();
00432 }
00433 else
00434 {
00435 std::cerr << "one of the endless objects that were leaky last time created!\n";
00436
00437 }
00438 }
00439 }
00440 #endif
00441
00442 #ifdef LEAKFINDER
00443 #ifdef PROFILER
00444 chunk(ret).realSize = size;
00445 #endif
00446 chunk(ret).array=info.array;
00447 chunk(ret).checksum=info.checksum;
00448 #endif
00449
00450 #ifdef DEBUG
00451 wmemset(static_cast< wchar_t * >( data(ret) ), wchar_t(0xfedabeef), size / sizeof( wchar_t ));
00452 #else
00453 wmemset(static_cast< wchar_t * >( data(ret) ), 0, size / sizeof( wchar_t ));
00454 #endif
00455
00456 #ifdef MEM_DEB_SMALL
00457 Check();
00458 #endif
00459
00460 return data(ret);
00461
00462 tASSERT(0);
00463 return NULL;
00464 }
00465
00466 static memblock * Dispose(void *p, int &size, tAllocationInfo const & info, bool keep=false){
00467 chunkinfo &c=((chunkinfo *)p)[-1];
00468 size=c.size_in_dwords*4;
00469
00470 #ifdef PROFILER
00471 if (c.checksum >=0 && c.checksum < MAXCHECKSUM){
00472 checksum_blocks[c.checksum]--;
00473 checksum_bytes [c.checksum]-=c.realSize;
00474 }
00475 #else
00476 #ifdef LEAKFINDER
00477 tASSERT(c.checksum>=-1 && c.checksum < MAXCHECKSUM);
00478 #endif
00479 #endif
00480
00481 #ifndef WIN32 // grr. on windows, this assertion fails on calls from STL.
00482 tASSERT( c.array == info.array );
00483 #endif
00484
00485 if (size==0){
00486 bool o = c.occupied;
00487
00488 c.occupied=false;
00489 if (o) free(&c);
00490 return NULL;
00491 }
00492
00493 tASSERT(c.occupied == 1);
00494 if (!c.occupied)
00495 return NULL;
00496
00497 #ifdef DEBUG
00498 wmemset(static_cast< wchar_t * >( p ), wchar_t(0xbadf00d), size / sizeof( wchar_t ));
00499 #else
00500 wmemset(static_cast< wchar_t * >( p ), 0, size / sizeof( wchar_t ) );
00501 #endif
00502
00503 memblock *myblock=(
00504 (memblock *)(void *)
00505 (
00506 ( (char *)(void *)p ) -
00507 ( (sizeof(chunkinfo)+size+SAFETYBYTES)*c.pos
00508 + sizeof(chunkinfo) )
00509 ) ) - 1;
00510
00511 c.occupied=false;
00512
00513
00514
00515 #ifndef DOUBLEFREEFINDER
00516 if (keep)
00517 return NULL;
00518
00519 #ifdef WIN32
00520 EnterCriticalSection(&mutex);
00521 #endif
00522
00523 tASSERT(myblock -> value < myblock->myman->blocksize);
00524 c.prev=0;
00525 c.next=myblock->first_free;
00526 myblock->first_free=c.pos+1;
00527 if (c.next) myblock->chunk(c.next-1).prev=c.pos+1;
00528
00529 myblock->value++;
00530 #endif
00531
00532
00533 return myblock;
00534 }
00535
00536 static memblock * create(tMemManager *man){
00537
00538 void *mem = malloc(man->blocksize * (SAFETYBYTES + man->size + sizeof(chunkinfo))
00539 + sizeof(memblock));
00540
00541 return new(mem) memblock(man);
00542 }
00543
00544 static void destroy(memblock * b){
00545 b->~memblock();
00546 free((void *)b);
00547 }
00548
00549 void Check(){
00550 #ifdef DEBUG
00551 tASSERT (size == myman->size);
00552
00553 tASSERT (value >=0);
00554 tASSERT (value <= myman->blocksize);
00555
00556 for(int i=myman->blocksize-1;i>=0;i--){
00557 tASSERT(chunk(i).pos == i);
00558
00559 for (int j=SAFETYBYTES-1;j>=0;j--){
00560 char a=safety(i)[j];
00561 char b=j^PAD;
00562 tASSERT(a==b);
00563 }
00564 }
00565 #endif
00566 }
00567
00568 #ifdef LEAKFINDER
00569 void dumpleaks(std::ostream &s){
00570 for (int i=myman->blocksize-1;i>=0;i--)
00571 if (chunk(i).occupied && chunk(i).checksum >= 0 ){
00572 s << chunk(i).checksum << " " << chunk(i).counter << '\n';
00573 leak();
00574 }
00575 }
00576 #endif
00577 };
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 bool tMemManager::SwapIf(int i,int j){
00590 if (i==j || i<0) return false;
00591
00592 memblock *e1=blocks(i),*e2=blocks(j);
00593 if (e1->value > e2->value){
00594 Swap(blocks(i),blocks(j));
00595 e1->hID=j;
00596 e2->hID=i;
00597 return true;
00598 }
00599 else
00600 return false;
00601
00602 }
00603
00604 tMemManager::~tMemManager(){
00605 #ifdef LEAKFINDER
00606 bool warn = true;
00607 #ifdef HAVE_LIBZTHREAD
00608 warn = false;
00609 #endif
00610
00611 if (inited){
00612
00613 std::ofstream lw(leakname);
00614 lw << "\n\n";
00615 tMemMan::Profile();
00616 }
00617 #endif
00618
00619 #ifdef WIN32
00620 if (inited)
00621 DeleteCriticalSection(&mutex);
00622 #endif
00623
00624 inited = false;
00625
00626
00627 int i;
00628 for (i=blocks.Len()-1;i>=0;i--){
00629 if (blocks(i)->value==blocksize)
00630 memblock::destroy(blocks(i));
00631 else{
00632 #ifdef LEAKFINDER
00633 if ( warn )
00634 {
00635 std::cout << "Memmanager warning: leaving block untouched.\n";
00636 warn = false;
00637 }
00638 std::ofstream l(leakname,std::ios::app);
00639 blocks(i)->dumpleaks(l);
00640 #endif
00641 }
00642 }
00643
00644 for (i=full_blocks.Len()-1;i>=0;i--){
00645 if (full_blocks(i)->value==blocksize)
00646 memblock::destroy(full_blocks(i));
00647 else{
00648 #ifdef LEAKFINDER
00649 if ( warn )
00650 {
00651 std::cout << "Memmanager warning: leaving block untouched.\n";
00652 warn = false;
00653 }
00654 std::ofstream l(leakname,std::ios::app);
00655 full_blocks(i)->dumpleaks(l);
00656 #endif
00657 }
00658 }
00659
00660 }
00661
00662 tMemManager::tMemManager(int s,int bs):size(s),blocksize(s){
00663
00664 if (blocksize>255)
00665 blocksize=255;
00666 semaphore = 1;
00667
00668 tBottleNeck neck;
00669
00670 #ifdef WIN32
00671 if (!inited)
00672 InitializeCriticalSection(&mutex);
00673 #endif
00674
00675 inited = true;
00676 }
00677
00678 tMemManager::tMemManager(int s):size(s){
00679 tBottleNeck neck;
00680
00681 inited = false;
00682
00683 blocks.SetLen(0);
00684 full_blocks.SetLen(0);
00685 blocksize=16000/(s+sizeof(chunkinfo)+SAFETYBYTES);
00686 if (blocksize>252)
00687 blocksize=252;
00688
00689 semaphore = 1;
00690
00691 #ifdef LEAKFINDER
00692 if (size == 0){
00693 for ( int i = MAXCHECKSUM-1; i>=0; --i )
00694 {
00695 leaks[i] = 0;
00696 counter[i] = 0;
00697 #ifdef PROFILER
00698 checksum_filename[i] = 0;
00699 checksum_classname[i] = 0;
00700 checksum_line[i] = 0;
00701 checksum_blocks[i] = 0;
00702 checksum_bytes[i] = 0;
00703 #endif
00704 }
00705
00706 std::ifstream l(leakname);
00707 while (l.good() && !l.eof()){
00708 int cs,ln;
00709 l >> cs >> ln;
00710
00711 if (cs>=0 && cs < MAXCHECKSUM && (ln < leaks[cs] || leaks[cs] == 0))
00712 leaks[cs]=ln;
00713 }
00714 }
00715 if (!inited){
00716
00717 std::ofstream lw(leakname);
00718 lw << "\n\n";
00719 }
00720 #endif
00721
00722 #ifdef WIN32
00723 if (!inited)
00724 InitializeCriticalSection(&mutex);
00725 #endif
00726
00727 inited = true;
00728 }
00729
00730
00731 void tMemManager::CheckHeap(){
00732 for(int i=blocks.Len()-1;i>0;i--){
00733 memblock *current=blocks(i);
00734 memblock *low=blocks(Lower(i));
00735 if (Lower(UpperL(i))!=i || Lower(UpperR(i))!=i)
00736 tERR_ERROR_INT("Error in lower/upper " << i << "!");
00737
00738 if (low->value>current->value)
00739 tERR_ERROR_INT("Heap structure corrupt!");
00740 }
00741 }
00742
00743
00744 void tMemManager::SwapDown(int j){
00745 int i=j;
00746
00747
00748 do{
00749 j=i;
00750 i=Lower(j);
00751 }
00752 while(SwapIf(i,j));
00753
00754
00755 #ifdef MEM_DEB
00756 CheckHeap();
00757 #endif
00758 }
00759
00760 void tMemManager::SwapUp(int i){
00761 #ifdef MEM_DEB
00762
00763
00764
00765
00766
00767
00768 #endif
00769
00770 int ul,ur;
00771 bool goon=1;
00772 while(goon && UpperL(i)<blocks.Len()){
00773 ul=UpperL(i);
00774 ur=UpperR(i);
00775 if(ur>=blocks.Len() ||
00776 blocks(ul)->value < blocks(ur)->value){
00777 goon=SwapIf(i,ul);
00778 i=ul;
00779 }
00780 else{
00781 goon=SwapIf(i,ur);
00782 i=ur;
00783 }
00784 }
00785
00786 #ifdef MEM_DEB
00787 CheckHeap();
00788 #endif
00789
00790 }
00791
00792 void tMemManager::Insert(memblock *e){
00793 blocks.Add(e,e->hID);
00794
00795 SwapDown(blocks.Len()-1);
00796
00797 #ifdef MEM_DEB
00798 CheckHeap();
00799 #endif
00800 }
00801
00802 void tMemManager::Remove(memblock *e){
00803 int i=e->hID;
00804
00805 if(i<0 || this != e->myman)
00806 tERR_ERROR_INT("Element is not in this heap!");
00807
00808 Remove(i);
00809
00810 #ifdef MEM_DEB
00811 CheckHeap();
00812 #endif
00813 }
00814
00815 void tMemManager::Replace(int i){
00816 if (i>=0 && i < blocks.Len()){
00817 if (i==0 || blocks(i)->value > blocks(Lower(i))->value)
00818 SwapUp(i);
00819 else
00820 SwapDown(i);
00821
00822 #ifdef MEM_DEB
00823 CheckHeap();
00824 #endif
00825 }
00826 }
00827
00828 void tMemManager::Replace(memblock *e){
00829 int i=e->hID;
00830
00831 if(i<0 || this != e->myman)
00832 tERR_ERROR_INT("Element is not in this heap!");
00833
00834 Replace(i);
00835
00836 #ifdef MEM_DEB
00837 CheckHeap();
00838 #endif
00839 }
00840
00841 memblock * tMemManager::Remove(int i){
00842 if (i>=0 && i<blocks.Len()){
00843 memblock *ret=blocks(i);
00844
00845 blocks.Remove(ret,ret->hID);
00846
00847
00848 if (i<blocks.Len())
00849 Replace(i);
00850
00851 #ifdef MEM_DEB
00852 CheckHeap();
00853 #endif
00854
00855 return ret;
00856 }
00857 return NULL;
00858 }
00859
00860 void * tMemManager::Alloc( tAllocationInfo const & info ){
00861 semaphore--;
00862 if (semaphore<0 || size == 0){
00863 semaphore++;
00864 return AllocDefault(info, size);
00865 }
00866
00867 #ifdef WIN32
00868 EnterCriticalSection(&mutex);
00869 #endif
00870
00871 if (blocks.Len()==0)
00872 Insert(memblock::create(this));
00873
00874
00875 memblock *block=blocks(0);
00876 tASSERT (block->size == size);
00877 void *mem = block->Alloc( info );
00878
00879 if (block->value == 0){
00880 Remove(block);
00881 full_blocks.Add(block,block->hID);
00882 }
00883
00884 #ifdef WIN32
00885 LeaveCriticalSection(&mutex);
00886 #endif
00887
00888 semaphore++;
00889 return mem;
00890 }
00891
00892 void tMemManager::complete_Dispose(memblock *block){
00893 #ifdef MEM_DEB_SMALL
00894 block->Check();
00895 #endif
00896
00897 semaphore--;
00898 if (semaphore>=0){
00899 if (block->value == 1){
00900 full_blocks.Remove(block,block->hID);
00901 Insert(block);
00902 }
00903 else{
00904 Replace(block);
00905 }
00906 }
00907
00908
00909 semaphore++;
00910
00911 #ifdef MEM_DEB_SMALL
00912 block->Check();
00913 #endif
00914 }
00915
00916 void tMemManager::Check(){
00917 #ifdef DEBUG_EXPENSIVE
00918 if ( !inited )
00919 return;
00920
00921 CheckHeap();
00922 int i;
00923 for (i=blocks.Len()-1;i>=0;i--)
00924 {
00925 blocks(i)->Check();
00926 tASSERT (blocks(i)->myman == this);
00927 tASSERT (blocks(i)->size == size);
00928 }
00929 for (i=full_blocks.Len()-1;i>=0;i--)
00930 {
00931 if ( full_blocks(i) )
00932 {
00933 full_blocks(i)->Check();
00934 tASSERT (full_blocks(i)->myman == this);
00935 tASSERT (full_blocks(i)->size == size);
00936 }
00937 }
00938 #endif
00939 }
00940
00941
00942 #define MAX_SIZE 109
00943
00944
00945 static tMemManager memman[MAX_SIZE+1]={
00946 tMemManager(0),
00947 tMemManager(4),
00948 tMemManager(8),
00949 tMemManager(12),
00950 tMemManager(16),
00951 tMemManager(20),
00952 tMemManager(24),
00953 tMemManager(28),
00954 tMemManager(32),
00955 tMemManager(36),
00956 tMemManager(40),
00957 tMemManager(44),
00958 tMemManager(48),
00959 tMemManager(52),
00960 tMemManager(56),
00961 tMemManager(60),
00962 tMemManager(64),
00963 tMemManager(68),
00964 tMemManager(72),
00965 tMemManager(76),
00966 tMemManager(80),
00967 tMemManager(84),
00968 tMemManager(88),
00969 tMemManager(92),
00970 tMemManager(96),
00971 tMemManager(100),
00972 tMemManager(104),
00973 tMemManager(108),
00974 tMemManager(112),
00975 tMemManager(116),
00976 tMemManager(120),
00977 tMemManager(124),
00978 tMemManager(128),
00979 tMemManager(132),
00980 tMemManager(136),
00981 tMemManager(140),
00982 tMemManager(144),
00983 tMemManager(148),
00984 tMemManager(152),
00985 tMemManager(156),
00986 tMemManager(160),
00987 tMemManager(164),
00988 tMemManager(168),
00989 tMemManager(172),
00990 tMemManager(176),
00991 tMemManager(180),
00992 tMemManager(184),
00993 tMemManager(188),
00994 tMemManager(192),
00995 tMemManager(196),
00996 tMemManager(200),
00997 tMemManager(204),
00998 tMemManager(208),
00999 tMemManager(212),
01000 tMemManager(216),
01001 tMemManager(220),
01002 tMemManager(224),
01003 tMemManager(228),
01004 tMemManager(232),
01005 tMemManager(236),
01006 tMemManager(240),
01007 tMemManager(244),
01008 tMemManager(248),
01009 tMemManager(252),
01010 tMemManager(256),
01011 tMemManager(260),
01012 tMemManager(264),
01013 tMemManager(268),
01014 tMemManager(272),
01015 tMemManager(276),
01016 tMemManager(280),
01017 tMemManager(284),
01018 tMemManager(288),
01019 tMemManager(292),
01020 tMemManager(296),
01021 tMemManager(300),
01022 tMemManager(304),
01023 tMemManager(308),
01024 tMemManager(312),
01025 tMemManager(316),
01026 tMemManager(320),
01027 tMemManager(324),
01028 tMemManager(328),
01029 tMemManager(332),
01030 tMemManager(336),
01031 tMemManager(340),
01032 tMemManager(344),
01033 tMemManager(348),
01034 tMemManager(352),
01035 tMemManager(356),
01036 tMemManager(360),
01037 tMemManager(364),
01038 tMemManager(368),
01039 tMemManager(372),
01040 tMemManager(376),
01041 tMemManager(380),
01042 tMemManager(384),
01043 tMemManager(388),
01044 tMemManager(392),
01045 tMemManager(396),
01046 tMemManager(400),
01047 tMemManager(404),
01048 tMemManager(408),
01049 tMemManager(412),
01050 tMemManager(416),
01051 tMemManager(420),
01052 tMemManager(424),
01053 tMemManager(428),
01054 tMemManager(432),
01055 tMemManager(436)
01056 };
01057
01058
01059 void tMemManager::Dispose(tAllocationInfo const & info, void *p, bool keep){
01060 int size;
01061
01062 if (!p)
01063 return;
01064
01065 memblock *block = memblock::Dispose(p,size,info, keep);
01066 #ifndef DOUBLEFREEFINDER
01067 if (inited && block){
01068 tBottleNeck neck;
01069 memman[size >> 2].complete_Dispose(block);
01070 #ifdef WIN32
01071 LeaveCriticalSection(&mutex);
01072 #endif
01073 }
01074 #else
01075 block = 0;
01076 #endif
01077 }
01078
01079 void *tMemManager::AllocDefault(tAllocationInfo const & info, size_t s){
01080 #ifdef LEAKFINDER
01081 void *ret=malloc(s+sizeof(chunkinfo));
01082 ((chunkinfo *)ret)->checksum=info.checksum;
01083 ((chunkinfo *)ret)->array=info.array;
01084 #ifdef PROFILER
01085 ((chunkinfo *)ret)->realSize=s;
01086 if ( info.checksum >= 0 )
01087 {
01088 if (!counter[info.checksum]){
01089 checksum_filename [info.checksum] = info.filename;
01090 checksum_classname[info.checksum] = info.classname;
01091 checksum_line [info.checksum] = info.line;
01092 }
01093 checksum_blocks[info.checksum]++;
01094 checksum_bytes[info.checksum]+=s;
01095 }
01096 #endif
01097 #else
01098 void *ret=malloc(s+sizeof(chunkinfo));
01099 #endif
01100 ((chunkinfo *)ret)->size_in_dwords=0;
01101 ((chunkinfo *)ret)->occupied=true;
01102 ret = ((chunkinfo *)ret)+1;
01103 return ret;
01104 }
01105
01106 void *tMemMan::Alloc(tAllocationInfo const & info, size_t s){
01107 #ifndef DONTUSEMEMMANAGER
01108 #ifdef MEM_DEB
01109 #ifdef WIN32
01110 tASSERT(_CrtCheckMemory());
01111 #endif
01112 Check();
01113 #endif
01114 void *ret;
01115 if (inited && s < (MAX_SIZE << 2))
01116 {
01117 tBottleNeck neck;
01118 ret=memman[((s+3)>>2)].Alloc( info );
01119 }
01120 else
01121 {
01122 ret=tMemManager::AllocDefault(info, s);
01123 }
01124 #ifdef MEM_DEB
01125 Check();
01126 #ifdef WIN32
01127 tASSERT(_CrtCheckMemory());
01128 #endif
01129 #endif
01130 return ret;
01131
01132 #else
01133 return malloc(s);
01134 #endif
01135
01136 }
01137
01138 void tMemMan::DisposeButKeep( tAllocationInfo const & info, void *p){
01139 #ifndef DONTUSEMEMMANAGER
01140 #ifdef MEM_DEB
01141 #ifdef WIN32
01142 tASSERT(_CrtCheckMemory());
01143 #endif
01144 Check();
01145 #endif
01146 tMemManager::Dispose(info, p, true);
01147 #ifdef MEM_DEB
01148 Check();
01149 #ifdef WIN32
01150 tASSERT(_CrtCheckMemory());
01151 #endif
01152 #endif
01153 #endif
01154 }
01155
01156 void tMemMan::Dispose(tAllocationInfo const & info, void *p){
01157 #ifndef DONTUSEMEMMANAGER
01158 #ifdef MEM_DEB
01159 #ifdef WIN32
01160 tASSERT(_CrtCheckMemory());
01161 #endif
01162 Check();
01163 #endif
01164 tMemManager::Dispose(info, p );
01165 #ifdef MEM_DEB
01166 Check();
01167 #ifdef WIN32
01168 tASSERT(_CrtCheckMemory());
01169 #endif
01170 #endif
01171 #else
01172 free(p);
01173 #endif
01174 }
01175
01176
01177 void tMemManBase::Check(){
01178 if (!inited)
01179 return;
01180
01181 #ifdef WIN32
01182 EnterCriticalSection(&mutex);
01183 #endif
01184
01185 for (int i=MAX_SIZE;i>=0;i--)
01186 memman[i].Check();
01187
01188 #ifdef WIN32
01189 LeaveCriticalSection(&mutex);
01190 #endif
01191 }
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205 #ifdef NEW
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218 #ifdef WIN32
01219 #ifdef DEDICATED
01220 #ifdef DEBUG
01221 #if 0
01222 void * operator new(
01223 size_t size,
01224 int nBlockUse,
01225 const char * file,
01226 int l
01227 )
01228 {
01229 #ifdef LEAKFINDER
01230 fileName=file;
01231 classname="XXX";
01232 line=l;
01233
01234 checksum =
01235 #ifndef PROFILER
01236 size +
01237 #endif
01238 line * 19671;
01239
01240 checksum = checksum % MAXCHECKSUM;
01241 int c=1379;
01242 while (*file){
01243 checksum = (checksum + (*file)*c) % MAXCHECKSUM;
01244 c = (c * 79 ) % MAXCHECKSUM;
01245 file++;
01246 }
01247
01248 #ifdef PROFILER
01249 while (checksum_fileName[checksum] && (checksum_fileName[checksum] != fileName || checksum_line[checksum] != line))
01250 checksum = (checksum+1) % MAXCHECKSUM;
01251 #endif
01252
01253 #endif
01254 return tMemMan::Alloc(size);
01255
01256
01257 }
01258 #endif
01259 #endif
01260 #endif
01261 #endif
01262
01263
01264 void* _cdecl operator new (size_t size) THROW_BADALLOC{
01265 tAllocationInfo info( false );
01266
01267 #ifdef LEAKFINDER
01268 #ifndef HAVE_LIBZTHREAD
01269 info.checksum = size;
01270 #endif
01271 #endif
01272 return tMemMan::Alloc(info, size);
01273 }
01274
01275 void _cdecl operator delete(void *ptr) THROW_NOTHING{
01276 tAllocationInfo info( false );
01277
01278 if (ptr)
01279 tMemMan::Dispose(info, ptr);
01280 }
01281
01282 void operator delete(void *ptr,bool keep) THROW_NOTHING{
01283 tAllocationInfo info( false );
01284
01285 if (ptr){
01286 if (keep)
01287 tMemMan::DisposeButKeep(info, ptr);
01288 else
01289 tMemMan::Dispose(info, ptr);
01290
01291 }
01292 }
01293
01294
01295
01296 void* operator new (size_t size,const char *classn,const char *file,int l) THROW_BADALLOC{
01297 tAllocationInfo info( false );
01298 #ifdef LEAKFINDER
01299 info.filename=file;
01300 info.classname=classn;
01301 info.line=l;
01302
01303 info.checksum =
01304 #ifndef PROFILER
01305 size +
01306 #endif
01307 info.line * 19671;
01308
01309 int c=1379;
01310 while (*file){
01311 info.checksum = (info.checksum + (*file)*c) % MAXCHECKSUM;
01312 c = (c * 79 ) % MAXCHECKSUM;
01313 file++;
01314 }
01315 while (*classn){
01316 info.checksum = (info.checksum + (*classn)*c) % MAXCHECKSUM;
01317 c = (c * 79 ) % MAXCHECKSUM;
01318 classn++;
01319 }
01320
01321 #ifdef PROFILER
01322 while (checksum_filename[info.checksum] && (checksum_filename[info.checksum] != info.filename || checksum_line[info.checksum] != info.line))
01323 info.checksum = (info.checksum+1) % MAXCHECKSUM;
01324 #endif
01325
01326 #endif
01327 return tMemMan::Alloc(info, size);
01328 }
01329
01330 void operator delete (void *ptr,const char *classname,const char *file,int line) THROW_NOTHING{
01331 tAllocationInfo info( false );
01332
01333 if (ptr) tMemMan::Dispose(info, ptr);
01334 }
01335
01336 void* operator new[] (size_t size) THROW_BADALLOC{
01337 tAllocationInfo info( true );
01338 #ifdef LEAKFINDER
01339 #ifndef HAVE_LIBZTHREAD
01340 info.checksum = size % MAXCHECKSUM;
01341 #endif
01342 #endif
01343 return tMemMan::Alloc(info, size);
01344 }
01345
01346 void operator delete[](void *ptr) THROW_NOTHING {
01347 tAllocationInfo info( true );
01348
01349 if (ptr)
01350 tMemMan::Dispose(info, ptr);
01351 }
01352
01353
01354
01355 void* operator new[] (size_t size,const char *classn,const char *file,int l) THROW_BADALLOC{
01356 tAllocationInfo info( true );
01357 #ifdef LEAKFINDER
01358 info.filename=file;
01359 info.classname=classn;
01360 info.line=l;
01361
01362 info.checksum =
01363 #ifndef PROFILER
01364 size +
01365 #endif
01366 info.line * 19671;
01367
01368 int c=1379;
01369 while (*file){
01370 info.checksum = (info.checksum + (*file)*c) % MAXCHECKSUM;
01371 c = (c * 79 ) % MAXCHECKSUM;
01372 file++;
01373 }
01374 while (*classn){
01375 info.checksum = (info.checksum + (*classn)*c) % MAXCHECKSUM;
01376 c = (c * 79 ) % MAXCHECKSUM;
01377 classn++;
01378 }
01379
01380 #ifdef PROFILER
01381 while (checksum_filename[info.checksum] && (checksum_filename[info.checksum] != info.filename || checksum_line[info.checksum] != info.line))
01382 info.checksum = (info.checksum+1) % MAXCHECKSUM;
01383 #endif
01384
01385 #endif
01386 return tMemMan::Alloc(info, size);
01387 }
01388
01389 void operator delete[] (void *ptr,const char *classname,const char *file,int line) THROW_NOTHING{
01390 tAllocationInfo info( true );
01391
01392 if (ptr) tMemMan::Dispose(info, ptr);
01393 }
01394
01395 #endif
01396
01397
01398
01399
01400 #ifdef PROFILER
01401 static int compare(const void *a, const void *b){
01402 int A = checksum_bytes[*((const int *)a)];
01403 int B = checksum_bytes[*((const int *)b)];
01404
01405 if (A<B)
01406 return -1;
01407 if (A>B)
01408 return 1;
01409
01410 return 0;
01411 }
01412
01413
01414
01415
01416
01417 #endif
01418
01419
01420 #ifdef WIN32
01421 #define snprintf _snprintf
01422 #endif
01423
01424 void tMemManBase::Profile(){
01425 tBottleNeck neck;
01426 #ifdef PROFILER
01427
01428 int sort_checksum[MAXCHECKSUM];
01429 int size=0,i;
01430
01431 for (i=MAXCHECKSUM-1;i>=0;i--)
01432 if (checksum_blocks[i])
01433 sort_checksum[size++] = i;
01434
01435 qsort(sort_checksum, size, sizeof(int), &compare);
01436
01437 static int num=1;
01438
01439 char name[100];
01440 snprintf( name, 99, "memprofile%d.txt", num++ );
01441
01442
01443
01444
01445
01446 FILE *f = fopen( name, "w" );
01447
01448
01449 int total_blocks=0,total_bytes =0;
01450
01451 for (i=size-1; i>=0; i--)
01452 {
01453 int cs = sort_checksum[i];
01454 const char *fn = checksum_filename[cs];
01455 const char *cn = checksum_classname[cs];
01456
01457 if (!fn)
01458 fn = "XXX";
01459 if (!cn)
01460 cn = "XXX";
01461
01462 fprintf( f, "%d\t%d\t%30s\t%80s\t%d\t%d\t\n", checksum_blocks[cs], checksum_bytes[cs],cn, fn , checksum_line[cs], cs );
01463
01464 total_blocks += checksum_blocks[cs];
01465 total_bytes += checksum_bytes[cs];
01466 }
01467
01468 fclose( f );
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498 #endif
01499 }
01500
01501 #ifdef HAVE_LIBEFENCE
01502 class eFence
01503 {
01504 public:
01505 eFence()
01506 {
01507 EF_newFrame();
01508 }
01509 ~eFence()
01510 {
01511 EF_delFrame();
01512 }
01513 };
01514
01515 static eFence fence;
01516 #endif
01517
01518 #ifndef DONTUSEMEMMANAGER
01519 void * real_calloc( size_t nmemb, size_t size )
01520 {
01521 return calloc( nmemb, size );
01522 }
01523
01524 void * real_malloc( size_t size )
01525 {
01526 return malloc( size );
01527 }
01528
01529 void real_free( void * ptr )
01530 {
01531 free( ptr );
01532 }
01533
01534 void * real_realloc( void * ptr, size_t size )
01535 {
01536 return realloc( ptr, size );
01537 }
01538
01539 char * real_strdup( char const * ptr )
01540 {
01541 return strdup( ptr );
01542 }
01543
01544 void * real_mmove( void * ptr, size_t size )
01545 {
01546
01547 void * ret = tNEW(char)[size];
01548 memcpy( ret, ptr, size );
01549 real_free( ptr );
01550
01551 return ret;
01552 }
01553
01554 char * real_strmove( char * ptr )
01555 {
01556 if ( ptr )
01557 return static_cast< char * >( real_mmove( ptr, strlen( ptr ) + 1 ) );
01558 else
01559 return 0;
01560 }
01561
01562 #endif // DONTUSEMEMMANAGER
01563
01564 char * tStrDup( char const * s )
01565 {
01566 return real_strmove( strdup( s ) );
01567 }