/*++ Copyright (C) 1998-1999 Microsoft Corporation Module Name: NEWNEW.H Abstract: CReuseMemoryManager History: --*/ #ifndef __WBEM_NEW_NEW__H_ #define __WBEM_NEW_NEW__H_ #include "esscpol.h" #include class ESSCLI_POLARITY CReuseMemoryManager { protected: CCritSec m_cs; CFlexQueue m_Available; int m_nSize; int m_nMaxQueued; public: CReuseMemoryManager(size_t nSize, size_t nMaxQueued = 0 ) : m_nSize(nSize) { m_nMaxQueued = nMaxQueued == 0 ? 256 : nMaxQueued; } ~CReuseMemoryManager() { Clear(); } void* Allocate() { CInCritSec ics(&m_cs); if(m_Available.GetQueueSize() == 0) { return new BYTE[m_nSize]; } else { void* p = m_Available.Unqueue(); return p; } } void Free(void* p) { CInCritSec ics(&m_cs); if ( m_Available.GetQueueSize() < m_nMaxQueued ) { m_Available.Enqueue(p); } else { delete [] (BYTE*)p; } } void Clear() { CInCritSec ics(&m_cs); while(m_Available.GetQueueSize()) { delete [] (BYTE*)m_Available.Unqueue(); } } }; #define DWORD_ALIGNED(x) (((x) + 3) & ~3) #define QWORD_ALIGNED(x) (((x) + 7) & ~7) #ifdef _WIN64 #define DEF_ALIGNED QWORD_ALIGNED #else #define DEF_ALIGNED DWORD_ALIGNED #endif class ESSCLI_POLARITY CTempMemoryManager { protected: CCritSec m_cs; class CAllocation { private: size_t m_dwAllocationSize; size_t m_dwUsed; size_t m_dwFirstFree; static inline size_t GetHeaderSize() {return sizeof(CAllocation);} inline byte* GetStart() {return ((byte*)this) + GetHeaderSize();} inline byte* GetEnd() {return ((byte*)this) + m_dwAllocationSize;} public: size_t GetAllocationSize() {return m_dwAllocationSize;} size_t GetUsedSize() {return m_dwUsed;} static size_t GetMinAllocationSize(size_t dwBlock) {return dwBlock + GetHeaderSize();} void Init(size_t dwAllocationSize); void* Alloc(size_t nBlockSize); bool Contains(void* p); bool Free(size_t nBlockSize); void Destroy(); }; CPointerArray* m_pAllocations; DWORD m_dwTotalUsed; DWORD m_dwTotalAllocated; DWORD m_dwNumAllocations; DWORD m_dwNumMisses; protected: inline size_t RoundUp(size_t nSize) {return DEF_ALIGNED(nSize);} public: CTempMemoryManager(); ~CTempMemoryManager(); void* Allocate(size_t nBlockSize); void Free(void* p, size_t nBlockSize); void Clear(); }; #define MAX_ALLOCA_USE 100 template class CTempArray { protected: BYTE* m_a; BOOL m_bStack; int m_nByteSize; TArg* GetArray() {return (TArg*)m_a;} const TArg* GetArray() const {return (const TArg*)m_a;} public: inline CTempArray() : m_a(NULL), m_bStack(TRUE), m_nByteSize(0){} inline ~CTempArray() { if(!m_bStack) delete [] m_a; } operator TArg*() {return (TArg*)m_a;} operator const TArg*() const {return (const TArg*)m_a;} TArg& operator[](int nIndex) {return GetArray()[nIndex];} const TArg& operator[](int nIndex) const {return GetArray()[nIndex];} TArg& operator[](long lIndex) {return GetArray()[lIndex];} const TArg& operator[](long lIndex) const {return GetArray()[lIndex];} void SetMem(void* p) {m_a = (BYTE*)p;} BOOL SetSize(int nSize) { m_nByteSize = nSize * sizeof(TArg); if(m_nByteSize < MAX_ALLOCA_USE) { m_bStack = TRUE; return TRUE; } else { m_bStack = FALSE; return FALSE; } } int GetByteSize() {return m_nByteSize;} BOOL IsNull() {return (m_a == NULL);} }; // This macro initializes the CTempArray with a given size. First it "sets" the // size into the array, which returns TRUE if _alloca can be used. If so, it // uses alloca on the now-computed byte size of the array. #define INIT_TEMP_ARRAY(ARRAY, SIZE) \ ((ARRAY.SetMem( \ (ARRAY.SetSize(SIZE)) ? \ _alloca(ARRAY.GetByteSize()) : \ new BYTE[ARRAY.GetByteSize()] \ ) \ ), !ARRAY.IsNull()) \ #endif