//----------------------------------------------------------------------------- // // File: TRANSMEM.H // // Copyright Microsoft Corporation 1997, All Rights Reserved. // // Owner: NIKOS // // Description: This file contains memory routines and macros for using // EXCHMEM as a dynamic memory allocator. If your object can // be made fixed in size, it may be more appropriate to use // CPool especially if your object is allocated/freed often. // // Note: CPool never releases (frees) objects, so some sort of // free such objects may also be needed. // // Modified 2/98 by mikeswa - Added Multi-heap support //----------------------------------------------------------------------------- #ifndef __TRANSMEM_H__ #define __TRANSMEM_H__ #include #include #define HEAP_LOW_MEMORY_RESERVE 65536 // to be freed when we're low on memory //define number of exchmem heaps if not already defined #ifndef NUM_EXCHMEM_HEAPS #define NUM_EXCHMEM_HEAPS 0 #endif //NUM_EXCHMEM_HEAPS // // These three globals: // // HANDLE g_hTransHeap = NULL; // // must be declared somewhere in a C file so things will link properly. The macros // declared use these to store heap handles, etc. to make things work. // #ifdef __cplusplus extern "C" { #endif extern HANDLE g_hTransHeap; #ifdef __cplusplus } #endif // // TrHeapCreate needs to be called once at startup time to initialize Exchmem and create // the heap. // #ifdef __cplusplus __inline BOOL TrHeapCreate(DWORD dwFlags=0, DWORD dwInitialSize=1024000, DWORD dwMaxSize=0) #else __inline BOOL TrHeapCreate(DWORD dwFlags, DWORD dwInitialSize, DWORD dwMaxSize) #endif { if (g_hTransHeap) return FALSE; g_hTransHeap = ExchMHeapCreate(NUM_EXCHMEM_HEAPS, dwFlags, dwInitialSize, dwMaxSize); if (g_hTransHeap) return TRUE; else return FALSE; } // // TrHeapDestroy() needs to be called once at shutdown time to free the heap and it's contents. // // Note: Because the heap is destroyed before the module is finished unloading, all objects that // allocated memory must be destroyed (with delete) before the module is unloaded. If not // done, nasty crashes will result. This is a BAD thing to do: // // CObject g_Object; // // CObject::~CObject() // { // if (NULL != m_pBuffer) // { // TrFree(m_pBuffer); // m_pBuffer = NULL; // } // } // // since ~CObject() will be called AFTER TrHeapDestroy, and TrFree will be called on a (destroyed) heap. // __inline BOOL TrHeapDestroy(void) { BOOL b = TRUE; if (g_hTransHeap) { b = ExchMHeapDestroy(); g_hTransHeap = NULL; } return b; } // // TrCalloc: replacement for calloc() // __inline void * TrCalloc(unsigned int x, unsigned int y, char * szFile = __FILE__, unsigned int uiLine = __LINE__) { return g_hTransHeap ? ExchMHeapAllocDebug(x*y, szFile, uiLine) : NULL; } // // TrFree: replacement for free() __inline void TrFree(void *pv) { if (g_hTransHeap) { ExchMHeapFree(pv); } else { // Our allocs / frees are out of sync. #ifdef DEBUG DebugBreak(); #endif } } // TrMalloc: replacement for malloc() __inline void * TrMalloc(unsigned int size, char * szFile = __FILE__, unsigned int uiLine = __LINE__) { return g_hTransHeap ? ExchMHeapAllocDebug(size, szFile, uiLine) : NULL; } // TrRealloc: replacement for realloc() __inline void * TrRealloc(void *pv, unsigned int size, char * szFile = __FILE__, unsigned int uiLine = __LINE__) { return g_hTransHeap ? ExchMHeapReAllocDebug(pv, size, szFile, uiLine) : NULL; } #ifdef __cplusplus #define TransCONST const #else #define TransCONST #endif // TrStrdupW: replacement for wcsdup() __inline LPWSTR TrStrdupW(TransCONST LPWSTR pwszString) { LPWSTR pwszTmp = NULL; if (NULL == g_hTransHeap || NULL == pwszString) return NULL; pwszTmp = (LPWSTR) ExchMHeapAlloc((wcslen(pwszString) + 1) * sizeof(WCHAR)); if (NULL != pwszTmp) wcscpy(pwszTmp,pwszString); return pwszTmp; } // TrStrdupA: replacement for strdup() __inline LPSTR TrStrdupA(TransCONST LPSTR pszString) { LPSTR pszTmp = NULL; if (NULL == g_hTransHeap || NULL == pszString) return NULL; pszTmp = (LPSTR) ExchMHeapAlloc((strlen(pszString) + 1) * sizeof(CHAR)); if (NULL != pszTmp) strcpy(pszTmp,pszString); return pszTmp; } #ifdef _UNICODE #define TrStrdup(x) TrStrdupW(x) #else #define TrStrdup(x) TrStrdupA(x) #endif // // Please use the pv* macros... defined here allocators may change over time and this will // make it easy to change when needed. // #define pvMalloc(x) TrMalloc(x, __FILE__, __LINE__) #define FreePv(x) TrFree(x) #define pvCalloc(x,y) TrCalloc(x,y, __FILE__, __LINE__) #define pszStrdup(x) TrStrdup(x) #define pvRealloc(pv,size) TrRealloc(pv, size, __FILE__, __LINE__) #ifdef __cplusplus // Replacement for the default new() operator __inline void * __cdecl operator new(size_t stAllocateBlock) { return TrMalloc( stAllocateBlock ); } // Replacement for the default new() operator that allows //specification of file and line # // To use this allocator as your default allocator, simply use the following: //#define new TRANSMEM_NEW //NOTE: You must be careful when you redefine this macro... it may cause //problems with overloaded new operators (a la CPOOL or STL). #define TRANSMEM_NEW new(__FILE__, __LINE) __inline void * __cdecl operator new(size_t stAllocateBlock, char * szFile, unsigned int uiLine) { return TrMalloc( stAllocateBlock, szFile, uiLine ); } // Replacement for the default delete() operator __inline void __cdecl operator delete( void *pvMem ) { FreePv( pvMem ); } #endif // Convenient macro to set the pointer you freed to NULL as well #define TRFREE(x) \ if (NULL != x) \ { \ FreePv(x); \ x = NULL; \ } // Convenient macro to set the pointer to the object to NULL as well #define TRDELETE(x) \ if (NULL != x) \ { \ delete x; \ x = NULL; \ } #endif /* __TRANSMEM_H__ */