/***************************************************************************\ * * File: SimpleHelp.h * * Description: * SimpleHeap.h defines the heap operations used throughout DirectUser. See * below for a description of the different heaps. * * * History: * 11/26/1999: JStall: Created * * Copyright (C) 2000 by Microsoft Corporation. All rights reserved. * \***************************************************************************/ #if !defined(BASE__SimpleHeap_h__INCLUDED) #define BASE__SimpleHeap_h__INCLUDED #ifdef _X86_ #define USE_ROCKALL 1 // Use RockAll Research heap #endif #define USE_DYNAMICTLS 1 // Use Dynamic TLS using TlsAlloc() /***************************************************************************\ ***************************************************************************** * * Common memory management * ***************************************************************************** \***************************************************************************/ // // DirectUser supports multiple heaps used in different situations: // - Default: Heap shared by all threads within a common Context // - Context: Explicit heap for a (potentially different) Context- used cross-Context // - Process: Shared heap available by all Context's within the process. // // NOTE: It is VERY important that the Alloc() and Free() calls are properly // matched so that the memory is properly freed from the correct heap. If this // is not done, the memory will not be freed and will result in memory leaks // or potential process faults. // #if DBG #define DBG_HEAP_PARAMS , const char * pszFileName, int idxLineNum #define DBG_HEAP_USE do { pszFileName; idxLineNum; } while (0); #else #define DBG_HEAP_PARAMS #define DBG_HEAP_USE #endif class DUserHeap { // Construction public: DUserHeap(); virtual ~DUserHeap() { } enum EHeap { idProcessHeap = 0, idNtHeap = 1, #ifdef _DEBUG idCrtDbgHeap = 2, #endif #if USE_ROCKALL idRockAllHeap = 3, #endif }; // Operations public: virtual void * Alloc(SIZE_T cbSize, bool fZero DBG_HEAP_PARAMS) PURE; virtual void * Realloc(void * pvMem, SIZE_T cbNewSize DBG_HEAP_PARAMS) PURE; virtual void MultiAlloc(int * pnActual, void * prgAlloc[], int cItems, SIZE_T cbSize DBG_HEAP_PARAMS) PURE; virtual void Free(void * pvMem) PURE; virtual void MultiFree(int cItems, void * prgAlloc[], SIZE_T cbSize) PURE; public: void Lock(); BOOL Unlock(); // Data: protected: long m_cRef; }; HRESULT CreateProcessHeap(); void DestroyProcessHeap(); HRESULT CreateContextHeap(DUserHeap * pLinkHeap, BOOL fThreadSafe, DUserHeap::EHeap id, DUserHeap ** ppNewHeap); void DestroyContextHeap(DUserHeap * pHeapDestroy); void ForceSetContextHeap(DUserHeap * pHeapThread); extern DUserHeap * g_pheapProcess; extern DWORD g_tlsHeap; #define pProcessHeap g_pheapProcess #define pContextHeap (reinterpret_cast (TlsGetValue(g_tlsHeap))) #if DBG #define ClientAlloc(a) pContextHeap->Alloc(a, true, __FILE__, __LINE__) #define ClientAlloc_(a,b) pContextHeap->Alloc(a, b, __FILE__, __LINE__) #define ClientFree(a) pContextHeap->Free(a) #define ClientRealloc(a,b) pContextHeap->Realloc(a, b, __FILE__, __LINE__) #define ClientMultiAlloc(a,b,c,d) pContextHeap->MultiAlloc(a, b, c, d, __FILE__, __LINE__) #define ClientMultiFree(a,b,c) pContextHeap->MultiFree(a,b,c) #define ContextAlloc(p, a) p->Alloc(a, true, __FILE__, __LINE__) #define ContextAlloc_(p, a, b) p->Alloc(a, b, __FILE__, __LINE__) #define ContextFree(p, a) p->Free(a) #define ContextRealloc(p, a, b) p->Realloc(a, b, __FILE__, __LINE__) #define ContextMultiAlloc(p,a,b,c,d) p->MultiAlloc(a, b, c, d, __FILE__, __LINE__) #define ContextMultiFree(p,a, b, c) p->MultiFree(a,b,c) #define ProcessAlloc(a) pProcessHeap->Alloc(a, true, __FILE__, __LINE__) #define ProcessAlloc_(a, b) pProcessHeap->Alloc(a, b, __FILE__, __LINE__) #define ProcessFree(a) pProcessHeap->Free(a) #define ProcessRealloc(a, b) pProcessHeap->Realloc(a, b, __FILE__, __LINE__) #define ProcessMultiAlloc(a,b,c,d) pProcessHeap->MultiAlloc(a, b, c, d, __FILE__, __LINE__) #define ProcessMultiFree(a, b, c) pProcessHeap->MultiFree(a,b,c) void DumpData(void * pMem, int nLength); #else // DBG #define ClientAlloc(a) pContextHeap->Alloc(a, true) #define ClientAlloc_(a,b) pContextHeap->Alloc(a, b) #define ClientFree(a) pContextHeap->Free(a) #define ClientRealloc(a,b) pContextHeap->Realloc(a, b) #define ClientMultiAlloc(a,b,c,d) pContextHeap->MultiAlloc(a, b, c, d) #define ClientMultiFree(a,b,c) pContextHeap->MultiFree(a,b,c) #define ContextAlloc(p, a) p->Alloc(a, true) #define ContextAlloc_(p, a, b) p->Alloc(a, b) #define ContextFree(p, a) p->Free(a) #define ContextRealloc(p, a, b) p->Realloc(a, b) #define ContextMultiAlloc(p,a,b,c,d) p->MultiAlloc(a, b, c, d) #define ContextMultiFree(p,a, b, c) p->MultiFree(a,b,c) #define ProcessAlloc(a) pProcessHeap->Alloc(a, true) #define ProcessAlloc_(a, b) pProcessHeap->Alloc(a, b) #define ProcessFree(a) pProcessHeap->Free(a) #define ProcessRealloc(a, b) pProcessHeap->Realloc(a, b) #define ProcessMultiAlloc(a,b,c,d) pProcessHeap->MultiAlloc(a, b, c, d) #define ProcessMultiFree(a, b, c) pProcessHeap->MultiFree(a,b,c) #endif // DBG /***************************************************************************\ ***************************************************************************** * * operator new overloading * ***************************************************************************** \***************************************************************************/ #ifndef _INC_NEW #include #endif #if DBG // // Use this instead of the usual placement new syntax to avoid conflicts when // 'new' is re-defined to provide memory leak tracking (below) #define placement_new(pv, Class) PlacementNewImpl0(pv) #define placement_new1(pv, Class, p1) PlacementNewImpl1(pv, p1) #define placement_copynew(pv, Class, src) PlacementCopyNewImpl0(pv, src) #define placement_delete(pv, Class) (((Class *)(pv))->~Class()) #ifdef new #undef new #endif template inline T * PlacementNewImpl0(void *pv) { return new(pv) T; }; template inline T * PlacementNewImpl1(void *pv, Param1 p1) { return new(pv) T(p1); }; template inline T * PlacementCopyNewImpl0(void *pv, const T & t) { return new(pv) T(t); }; #else // DBG #define DEBUG_NEW new #define placement_new(pv, Class) new(pv) Class #define placement_new1(pv, Class, p1) new(pv) Class(p1) #define placement_copynew(pv, Class, src) new(pv) Class(src) #define placement_delete(pv, Class) (((Class *)(pv))->~Class()) #endif // DBG inline void * __cdecl operator new(size_t nSize) { void * pv = ClientAlloc(nSize); return pv; } inline void __cdecl operator delete(void * pvMem) { ClientFree(pvMem); } #if DBG template inline type * DoProcessNewDbg(const char * pszFileName, int idxLineNum); template inline type * DoClientNewDbg(const char * pszFileName, int idxLineNum); template inline type * DoContextNewDbg(DUserHeap * pHeap, const char * pszFileName, int idxLineNum); #else template inline type * DoProcessNew(); template inline type * DoClientNew(); template inline type * DoContextNew(DUserHeap * pHeap); #endif template inline void DoProcessDelete(type * pMem); template inline void DoClientDelete(type * pMem); template inline void DoContextDelete(DUserHeap * pHeap, type * pMem); #if DBG #define ProcessNew(t) DoProcessNewDbg(__FILE__, __LINE__) #define ClientNew(t) DoClientNewDbg(__FILE__, __LINE__) #define ContextNew(t,p) DoContextNewDbg(p, __FILE__, __LINE__) #else #define ProcessNew(t) DoProcessNew() #define ClientNew(t) DoClientNew() #define ContextNew(t,p) DoContextNew(p) #endif #define ProcessDelete(t,p) DoProcessDelete(p) #define ClientDelete(t,p) DoClientDelete(p) #define ContextDelete(t,h,p) DoContextDelete(p) // // To allocate memory on the stack that is aligned on an 8-byte boundary // we need to allocate an extra 4 bytes. All stack allocations are on // 4 byte boundaries. // #define STACK_ALIGN8_ALLOC(cb) \ ((void *) ((((UINT_PTR) _alloca(cb + 4)) + 7) & ~0x07)) #include "SimpleHeap.inl" #endif // BASE__SimpleHeap_h__INCLUDED