MercuryMemory.cpp

Go to the documentation of this file.
00001 //DO NOT INCLUDE MERCURYMEMORY.H!!!
00002 //If you include MercuryMemory.h, it'll try using the macro'd functions
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include "MercuryThreads.h"
00006 
00007 #include <map>
00008 using namespace std;
00009 
00010 void MercuryAMalloc( void * ptr, const char * file, const int line );
00011 void MercuryAFree( void * ptr );
00012 
00013 //YUCK! Redefinition of class, since we can't #include it.
00014 //Note: all this actually does is provide an instanciaton point for OVERALLFREE.
00015 class MercuryMemoryThrough
00016 {
00017 public:
00018     MercuryMemoryThrough() {}
00019     MercuryMemoryThrough( const char * fn, int ln ) { FILENAME=fn; LINENUMBER=ln; }
00020     template< class G >
00021     G * operator << ( G * t ) { MercuryAMalloc( (void*)t, FILENAME, LINENUMBER ); return t; }
00022     template< class G >
00023     G * operator >> ( G * t ) { MercuryAFree( (void*)t ); return t; }
00024     int LINENUMBER;
00025     const char * FILENAME;
00026 } OVERALLFREE;
00027 
00029 struct MInfoPair
00030 {
00031     MInfoPair() { }
00032     MInfoPair( const char * f, int l, int s ) { file = f; line = l; size = s; }
00033     const char * file;
00034     int line;
00035     int size;
00036 };
00037 
00038 bool        bMutexSetUp = false;
00039 COND_MUTEX( MemoryMutex );
00040 
00041 //Map for all currently allocated memory
00042 map< void *, MInfoPair > * AllMemoryMap = NULL;
00043 
00044 //Remove entry from allocated memory map
00045 void MapFree( void * addy )
00046 {
00047     LOCK_MUTEX( MemoryMutex );
00048 
00049     if ( AllMemoryMap == NULL )
00050         AllMemoryMap = new map< void *, MInfoPair >;
00051     if ( AllMemoryMap->find( addy ) == AllMemoryMap->end() )
00052         return;
00053     AllMemoryMap->erase(  AllMemoryMap->find( addy ) );
00054 
00055     UNLOCK_MUTEX( MemoryMutex );
00056 }
00057 
00058 //Add new entry for malloc'd data
00059 void MapAlloc( void * addy, const char * file, int line, int size )
00060 {
00061     if ( !bMutexSetUp )
00062     {
00063         bMutexSetUp = true;
00064         SETUP_MUTEX( MemoryMutex );
00065     }
00066     
00067     LOCK_MUTEX( MemoryMutex );
00068 
00069     if ( AllMemoryMap == NULL )
00070         AllMemoryMap = new map< void *, MInfoPair >;
00071     (*AllMemoryMap)[addy] = MInfoPair( file, line, size );
00072 
00073     UNLOCK_MUTEX( MemoryMutex );
00074 }
00075 
00076 void ResetAllLeakInfo()
00077 {
00078     if ( AllMemoryMap )
00079     {
00080         //NOTE: "delete" will still use the primary delete.
00081         //      so we can't actually use that here.
00082         //      free WILL LEAK LIKE A SIEVE! it's just a token attemp.
00083 
00084         //Why can't we use delete? (Call the destructor so we don't leak)
00085 
00086         //On second thought, let's not do this.  It can actually break because
00087         // of a circular dependency with delete _if_ the tempalate gets created
00088         // with MercuryMemory.h.  Besides,we only do this once, at the
00089         // beginning of the program, we won't miss this leaked ram.
00090         
00091         //AllMemoryMap->~map< void *, MInfoPair >();
00092         //free( AllMemoryMap );
00093     }
00094     AllMemoryMap = new map< void *, MInfoPair >;
00095 }
00096 
00097 //Just dump out all pending allocated memory
00098 void PrintAllLeakInfo()
00099 {
00100     for ( map< void *, MInfoPair >::iterator g = AllMemoryMap->begin(); g != AllMemoryMap->end(); g++ )
00101         printf( "Leak: %p: %s:%d\n", g->first, (g->second).file, (g->second).line );
00102 }
00103 
00105 class MemoryWatchForDestroy
00106 {
00107 public:
00108     ~MemoryWatchForDestroy() { if ( Print ) PrintAllLeakInfo(); }
00109     bool Print;
00110 };
00111 
00112 MemoryWatchForDestroy DPM;
00113 
00114 void SetPrintOnEnd( bool POD )
00115 {
00116     DPM.Print = POD;
00117 }
00118 
00119 void * MercuryMalloc( size_t x, const char * file, int line )
00120 {
00121     void * ret = malloc(x);
00122     MapAlloc( ret, file, line, x ); 
00123     return ret;
00124 }
00125 
00126 void * MercuryCalloc( size_t x, size_t y, const char * file, const int line )
00127 {
00128     void * ret = calloc(x,y);
00129     MapAlloc( ret, file, line, x*y ); 
00130     return ret;
00131 }
00132 
00133 void * MercuryRealloc( void * ptr, size_t x, const char * file, const int line )
00134 {
00135     void * ret = realloc(ptr,x);
00136     MapFree( ptr );
00137     MapAlloc( ret, file, line, x ); 
00138     return ret;
00139 }
00140 
00141 void MercuryAMalloc( void * ptr, const char * file, const int line )
00142 {
00143     MapAlloc( ptr, file, line, -1 ); 
00144 }
00145 
00146 void MercuryFree( void * ptr )
00147 {
00148     MapFree( ptr ); 
00149     free( ptr );
00150 }
00151 
00152 void MercuryAFree( void * ptr )
00153 {
00154     MapFree( ptr ); 
00155 }
00156 
00157 /* 
00158  * Copyright (c) 2006, Charles Lohr
00159  * All rights reserved.
00160  *
00161  * Redistribution and use in source and binary forms, with or
00162  * without modification, are permitted provided that the following
00163  * conditions are met:
00164  *  -   Redistributions of source code must retain the above
00165  *      copyright notice, this list of conditions and the following disclaimer.
00166  *  -   Redistributions in binary form must reproduce the above copyright
00167  *      notice, this list of conditions and the following disclaimer in
00168  *      the documentation and/or other materials provided with the distribution.
00169  *  -   Neither the name of the Mercury Engine nor the names of its
00170  *      contributors may be used to endorse or promote products derived from
00171  *      this software without specific prior written permission.
00172  *
00173  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00174  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00175  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00176  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00177  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00178  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00179  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00180  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00181  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00182  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00183  */

Hosted by SourceForge.net Logo