00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "Wm4FoundationPCH.h"
00018
00019 #ifdef WM4_MEMORY_MANAGER
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <cassert>
00035 #include <cstdlib>
00036 #include <fstream>
00037 #include "Wm4Memory.h"
00038 using namespace Wm4;
00039
00040 size_t Memory::ms_uiNumNewCalls = 0;
00041 size_t Memory::ms_uiNumDeleteCalls = 0;
00042 size_t Memory::ms_uiMaxAllowedBytes = 0;
00043 size_t Memory::ms_uiNumBlocks = 0;
00044 size_t Memory::ms_uiNumBytes = 0;
00045 Memory::Block* Memory::ms_pkHead = 0;
00046 Memory::Block* Memory::ms_pkTail = 0;
00047 bool Memory::ms_bTrackSizes = false;
00048 size_t Memory::ms_uiMaxAllocatedBytes = 0;
00049 size_t Memory::ms_uiMaxBlockSize = 0;
00050 size_t Memory::ms_auiHistogram[32] =
00051 {
00052 0,0,0,0,0,0,0,0,
00053 0,0,0,0,0,0,0,0,
00054 0,0,0,0,0,0,0,0,
00055 0,0,0,0,0,0,0,0
00056 };
00057
00058
00059 void* Memory::Allocate (size_t uiSize, char* acFile, unsigned int uiLine,
00060 bool bIsArray)
00061 {
00062 ms_uiNumNewCalls++;
00063
00064
00065
00066
00067
00068
00069
00070 size_t uiExtendedSize = sizeof(Block) + uiSize;
00071 char* pcAddr = (char*)malloc(uiExtendedSize);
00072
00073
00074 Block* pkBlock = (Block*)pcAddr;
00075 pkBlock->Size = uiSize;
00076 pkBlock->File = acFile;
00077 pkBlock->Line = uiLine;
00078 pkBlock->IsArray = bIsArray;
00079 InsertBlock(pkBlock);
00080
00081
00082 pcAddr += sizeof(Block);
00083
00084
00085 ms_uiNumBlocks++;
00086 ms_uiNumBytes += uiSize;
00087
00088 if (ms_uiMaxAllowedBytes > 0 && ms_uiNumBytes > ms_uiMaxAllowedBytes)
00089 {
00090
00091 assert(false);
00092 }
00093
00094
00095 if (ms_uiNumBytes > ms_uiMaxAllocatedBytes)
00096 {
00097 ms_uiMaxAllocatedBytes = ms_uiNumBytes;
00098 }
00099
00100
00101 if (ms_bTrackSizes)
00102 {
00103
00104 if (uiSize > ms_uiMaxBlockSize)
00105 {
00106 ms_uiMaxBlockSize = uiSize;
00107 }
00108
00109 unsigned int uiTwoPowerI = 1;
00110 int i;
00111 for (i = 0; i <= 30; i++, uiTwoPowerI <<= 1)
00112 {
00113 if (uiSize <= uiTwoPowerI)
00114 {
00115 ms_auiHistogram[i]++;
00116 break;
00117 }
00118 }
00119 if (i == 31)
00120 {
00121 ms_auiHistogram[i]++;
00122 }
00123 }
00124
00125 return (void*)pcAddr;
00126 }
00127
00128 void Memory::Deallocate (char* pcAddr, bool bIsArray)
00129 {
00130 ms_uiNumDeleteCalls++;
00131
00132 if (!pcAddr)
00133 {
00134 return;
00135 }
00136
00137
00138 pcAddr -= sizeof(Block);
00139
00140
00141
00142
00143 Block* pkBlock = (Block*)pcAddr;
00144 RemoveBlock(pkBlock);
00145
00146 #ifdef WM4_ENABLE_NEW_DELETE_MISMATCH_ASSERT
00147
00148 assert(pkBlock->IsArray == bIsArray);
00149 #endif
00150
00151
00152
00153
00154
00155
00156 assert(ms_uiNumBlocks > 0 && ms_uiNumBytes >= pkBlock->Size);
00157 ms_uiNumBlocks--;
00158 ms_uiNumBytes -= pkBlock->Size;
00159
00160
00161 free(pcAddr);
00162 }
00163
00164 void Memory::InsertBlock (Block* pkBlock)
00165 {
00166
00167 if (ms_pkTail)
00168 {
00169 pkBlock->Prev = ms_pkTail;
00170 pkBlock->Next = 0;
00171 ms_pkTail->Next = pkBlock;
00172 ms_pkTail = pkBlock;
00173 }
00174 else
00175 {
00176 pkBlock->Prev = 0;
00177 pkBlock->Next = 0;
00178 ms_pkHead = pkBlock;
00179 ms_pkTail = pkBlock;
00180 }
00181 }
00182
00183 void Memory::RemoveBlock (Block* pkBlock)
00184 {
00185 if (pkBlock->Prev)
00186 {
00187 pkBlock->Prev->Next = pkBlock->Next;
00188 }
00189 else
00190 {
00191 ms_pkHead = pkBlock->Next;
00192 }
00193
00194 if (pkBlock->Next)
00195 {
00196 pkBlock->Next->Prev = pkBlock->Prev;
00197 }
00198 else
00199 {
00200 ms_pkTail = pkBlock->Prev;
00201 }
00202 }
00203
00204 void Memory::GenerateReport (const char* acFilename)
00205 {
00206 std::ofstream kOStr(acFilename);
00207 assert(kOStr);
00208 if (!kOStr)
00209 {
00210 return;
00211 }
00212
00213
00214 kOStr << "Total number of 'new' calls = "
00215 << (unsigned int)ms_uiNumNewCalls << std::endl;
00216 kOStr << "Total number of 'delete' calls = "
00217 << (unsigned int)ms_uiNumDeleteCalls << std::endl;
00218 kOStr << "Maximum number of allocated bytes = "
00219 << (unsigned int)ms_uiMaxAllocatedBytes << std::endl << std::endl;
00220
00221
00222 kOStr << "Remaining number of blocks = "
00223 << (unsigned int)ms_uiNumBlocks << std::endl;
00224 kOStr << "Remaining number of bytes = "
00225 << (unsigned int)ms_uiNumBytes << std::endl << std::endl;
00226
00227
00228 size_t uiNumKnownBlocks = 0;
00229 size_t uiNumKnownBytes = 0;
00230 size_t uiNumUnknownBlocks = 0;
00231 size_t uiNumUnknownBytes = 0;
00232 Block* pkBlock = ms_pkHead;
00233 while (pkBlock)
00234 {
00235 if (pkBlock->File)
00236 {
00237 uiNumKnownBlocks++;
00238 uiNumKnownBytes += pkBlock->Size;
00239 }
00240 else
00241 {
00242 uiNumUnknownBlocks++;
00243 uiNumUnknownBytes += pkBlock->Size;
00244 }
00245 pkBlock = pkBlock->Next;
00246 }
00247
00248 #ifdef WM4_ENABLE_CONSISTENCY_CHECK
00249
00250 assert(uiNumKnownBlocks + uiNumUnknownBlocks == ms_uiNumBlocks);
00251 assert(uiNumKnownBytes + uiNumUnknownBytes == ms_uiNumBytes);
00252 #endif
00253
00254 kOStr << "Remaining number of known blocks = "
00255 << (unsigned int)uiNumKnownBlocks << std::endl;
00256 kOStr << "Remaining number of known bytes = "
00257 << (unsigned int)uiNumKnownBytes << std::endl << std::endl;
00258
00259 kOStr << "Remaining number of unknown blocks = "
00260 << (unsigned int)uiNumUnknownBlocks << std::endl;
00261 kOStr << "Remaining number of unknown bytes = "
00262 << (unsigned int)uiNumUnknownBytes << std::endl << std::endl;
00263
00264
00265 pkBlock = ms_pkHead;
00266 size_t uiIndex = 0;
00267 while (pkBlock)
00268 {
00269 kOStr << "block = " << (unsigned int)uiIndex << std::endl;
00270 kOStr << "size = " << (unsigned int)pkBlock->Size << std::endl;
00271 if (pkBlock->File)
00272 {
00273 kOStr << "file = " << pkBlock->File << std::endl;
00274 kOStr << "line = " << pkBlock->Line << std::endl;
00275 }
00276 else
00277 {
00278 kOStr << "file = unknown" << std::endl;
00279 kOStr << "line = unknown" << std::endl;
00280 }
00281 kOStr << "array = " << pkBlock->IsArray << std::endl << std::endl;
00282 pkBlock = pkBlock->Next;
00283 uiIndex++;
00284 }
00285 kOStr.close();
00286
00287 #ifdef WM4_ENABLE_CONSISTENCY_CHECK
00288
00289 assert(uiIndex == ms_uiNumBlocks);
00290 #endif
00291 }
00292
00293 void* operator new (size_t uiSize)
00294 {
00295 return Memory::Allocate(uiSize,0,0,false);
00296 }
00297
00298 void* operator new[](size_t uiSize)
00299 {
00300 return Memory::Allocate(uiSize,0,0,true);
00301 }
00302
00303 void* operator new (size_t uiSize, char* acFile, unsigned int uiLine)
00304 {
00305 return Memory::Allocate(uiSize,acFile,uiLine,false);
00306 }
00307
00308 void* operator new[] (size_t uiSize, char* acFile, unsigned int uiLine)
00309 {
00310 return Memory::Allocate(uiSize,acFile,uiLine,true);
00311 }
00312
00313 void operator delete (void* pvAddr)
00314 {
00315 Memory::Deallocate((char*)pvAddr,false);
00316 }
00317
00318 void operator delete[] (void* pvAddr)
00319 {
00320 Memory::Deallocate((char*)pvAddr,true);
00321 }
00322
00323 void operator delete (void* pvAddr, char*, unsigned int)
00324 {
00325 Memory::Deallocate((char*)pvAddr,false);
00326 }
00327
00328 void operator delete[] (void* pvAddr, char*, unsigned int)
00329 {
00330 Memory::Deallocate((char*)pvAddr,true);
00331 }
00332
00333
00334 #endif