text: /***************************************************************************\
  *
  * 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<DUserHeap *> (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 <new.h>
  #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<Class>(pv)
  #define placement_new1(pv, Class, p1)       PlacementNewImpl1<Class>(pv, p1)
  #define placement_copynew(pv, Class, src)   PlacementCopyNewImpl0<Class>(pv, src)
  #define placement_delete(pv, Class) (((Class *)(pv))->~Class())
  
  #ifdef new
  #undef new
  #endif
  
  template <class T>
  inline T *
  PlacementNewImpl0(void *pv)
  {
      return new(pv) T;
  };
  
  template <class T, class Param1>
  inline T *
  PlacementNewImpl1(void *pv, Param1 p1)
  {
      return new(pv) T(p1);
  };
  
  template <class T>
  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 <class type>   inline type *   DoProcessNewDbg(const char * pszFileName, int idxLineNum);
  template <class type>   inline type *   DoClientNewDbg(const char * pszFileName, int idxLineNum);
  template <class type>   inline type *   DoContextNewDbg(DUserHeap * pHeap, const char * pszFileName, int idxLineNum);
  #else
  template <class type>   inline type *   DoProcessNew();
  template <class type>   inline type *   DoClientNew();
  template <class type>   inline type *   DoContextNew(DUserHeap * pHeap);
  #endif
  template <class type>   inline void     DoProcessDelete(type * pMem);
  template <class type>   inline void     DoClientDelete(type * pMem);
  template <class type>   inline void     DoContextDelete(DUserHeap * pHeap, type * pMem);
  
  #if DBG
  #define ProcessNew(t)           DoProcessNewDbg<t>(__FILE__, __LINE__)
  #define ClientNew(t)            DoClientNewDbg<t>(__FILE__, __LINE__)
  #define ContextNew(t,p)         DoContextNewDbg<t>(p, __FILE__, __LINE__)
  #else
  #define ProcessNew(t)           DoProcessNew<t>()
  #define ClientNew(t)            DoClientNew<t>()
  #define ContextNew(t,p)         DoContextNew<t>(p)
  #endif
  #define ProcessDelete(t,p)      DoProcessDelete<t>(p)
  #define ClientDelete(t,p)       DoClientDelete<t>(p)
  #define ContextDelete(t,h,p)    DoContextDelete<t>(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
  