/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corp., 1991 **/ /**********************************************************************/ /* heap.hxx Expandable protected-mode heap classes: definition. These classes provide global "new" and "delete" operators which use the Windows LocalInit, et al., routines to manage as large a heap as is allocatable from GlobalAlloc. The class objects themselves are allocated from the local heap through LocalAlloc and LocalFree. FILE HISTORY: DavidHov 2-25-91 Created from CDD. Johnl 5-02-91 Added overloaded new prototype KeithMo 23-Oct-1991 Added forward references. beng 24-Dec-1991 Removed one-shot heaps to heapones.hxx */ #if !defined(_HEAP_HXX_) // In-line "operator new" that takes a pointer (placement syntax). inline void * CDECL operator new ( size_t cb, void * p ) { (void) cb; return p; } #define _HEAP_HXX_ // Only really expand this file if !Win32 #if !defined(WIN32) #include "base.hxx" #include "uiassert.hxx" #include "uibuffer.hxx" #ifndef _SIZE_T_DEFINED #include #endif // // Forward references. // DLL_CLASS LOCAL_HEAP_OBJ; DLL_CLASS BASE_HEAP; DLL_CLASS SUB_HEAP; DLL_CLASS GIANT_HEAP; DLL_CLASS MEM_MASTER; /************************************************************************* NAME: LOCL_HEAP_OBJ SYNOPSIS: An abstract class used to derive objects which will be allocated on the local (DS-based) heap. INTERFACE: operator new() - new operator operator delete() - dleete operator QueryBlockSize() - return heap size PARENT: BASE NOTE: This class won't presently work from a DLL. HISTORY: DavidHov 2-25-91 Created **************************************************************************/ DLL_CLASS LOCAL_HEAP_OBJ : public BASE { public: VOID * operator new ( size_t cb ); VOID operator delete ( VOID * pbBlock ); USHORT QueryBlockSize ( VOID * pbBlock ); private: static long _cLocalFreeErrors; }; /************************************************************************* NAME: BASE_HEAP SYNOPSIS: An abstract class used to derive heap objects. INTERFACE: BASE_HEAP() - constructor ~BASE_HEAP - destructor Alloc() - allocation Free() - Free. PARENT: LOCAL_HEAP_OBJ, BUFFER NOTE: This class won't presently work from a DLL. HISTORY: DavidHov 2-25-91 Created **************************************************************************/ DLL_CLASS BASE_HEAP : public LOCAL_HEAP_OBJ, public BUFFER { public: USHORT QuerySel() { return HIWORD( QueryPtr() ); } BASE_HEAP(); // Allocates the smallest possible buffer BASE_HEAP( USHORT cbInitialAllocSize ); ~BASE_HEAP(); virtual BYTE * Alloc ( USHORT cbBytes, USHORT fsFlags = 0 ) = 0; virtual BOOL Free ( BYTE * pbBlock ) = 0; }; /************************************************************************* NAME: SUB_HEAP SYNOPSIS: A single extension of a GIANT_HEAP, capable of allocating at most 64K of smaller items. INTERFACE: Indirect. Correct usage is only through MEM_MASTER and GIANT_HEAP. QueryOwner() - return the owner heap pointer. Alloc() - allocation Free() - free the memory CalcDeallocErrors() - return the count of deallocation errors PARENT: BASE_HEAP CAVEATS: This class and its subclasses, GIANT_HEAP and MEM_MASTER, use the SUB_HEAP operators "new" and "delete" to allocate their instances in the local heap through LocalAlloc and Local Free. NOTES: Again, usage is indirect. Intended use is only through the global replacement "new" and "delete" operators. In other words, if you link HEAPBIG.CXX into your program, you only have to call MEM_MASTER::Init or InitForDll. All SUB_HEAPs instances and the instances of its subclasses are linked onto a single circularly linked list maintained automatically by SUB_HEAP's constructors and destructors. This class won't presently work from a DLL. HISTORY: DavidHov 2-25-91 Created **************************************************************************/ DLL_CLASS SUB_HEAP: public BASE_HEAP { friend class GIANT_HEAP; friend class MEM_MASTER; protected: SUB_HEAP * _pFwd, * _pBack; enum SHtype { SHt_Invalid, SHt_DS, SHt_Normal } _type; USHORT _cbLargestFailed; // Size of largest failed allocation USHORT _cBlksOut; // Count of blocks outstanding ULONG _lcDeallocErrors; // Deallocation errors inline USHORT QuerySel () // Return selector of buffer { return HIWORD( QueryPtr() ); } GIANT_HEAP * _pOwner; // Pointer to owning GIANT_HEAP // Can only be constructed by MEM_MASTER, // or as part of a GIANT_HEAP // SUB_HEAP(); // used by MEM_MASTER; SHt_DS SUB_HEAP( USHORT cbInitialAllocSize ); // Normal constructor: SHt_Normal ~SUB_HEAP(); VOID Init(); // Initialze private data VOID Link(); // Link onto circular list VOID Unlink(); // Remove from circular list USHORT QueryBlockSize( BYTE * pbBlock ); // Return size of allocated block BOOL Walk () ; // Walk the heap-- Debugging. public: static MEM_MASTER * _pmmInstance; // Pointer to single instance // of MEM_MASTER // Returns pointer to owning GIANT_HEAP (which may be itself) // or NULL, implying that it's the DS heap (default GIANT_HEAP) virtual GIANT_HEAP * QueryOwner( ); virtual BYTE * Alloc( USHORT cbBytes, USHORT fsFlags = 0 ); virtual BOOL Free( BYTE * pbBlock ); virtual ULONG CalcDeallocErrors(); }; /************************************************************************* NAME: GIANT_HEAP SYNOPSIS: Logically, a GIANT_HEAP is one or more SUB_HEAPs. Since there must be at least one SUB_HEAP, GIANT_HEAP inherits from SUB_HEAP. The distinction lies in the "_pOwner" variable, which points to itself for GIANT_HEAPs. INTERFACE: Normally indirect. Typical usage is only through MEM_MASTER, since most programs will only ever have one GIANT_HEAP. Additional GIANT_HEAPs can be allocated to create "boundaries" to distinguish large-scale areas of memory allocation. Reference MEM_MASTER's "focus" routines for more information. GIANT_HEAP() - constructor ~GIANT_HEAP() - destructor SetBehavior() - set allocation behavior SetDeleteOnEmpty() - set delete on empty SetExtendOnFull() - set extend on full SetResizeOnEmpty() - set resize on empty QueryExpandErrors() - number of failed expansion attempts Alloc() - allocation Free() - free CalcDeallocErrors() - number of deallocation errors QueryTotalBlocks() - total blocks PARENT: SUB_HEAP NOTES: Normal usage is indirect. Intended use is through the global replacement "new" and "delete" operators. In other words, if you link HEAPBIG.CXX into your program, you only have to call MEM_MASTER Init. See SUB_HEAP, NOTES. This class won't presently work from a DLL. CAVEATS: See SUB_HEAP, CAVEATS. HISTORY: DavidHov 2-25-91 Created **************************************************************************/ #define GHbExtend (1<<0) #define GHbDelete (1<<1) #define GHbResize (1<<2) DLL_CLASS GIANT_HEAP : public SUB_HEAP { friend class MEM_MASTER; protected: // Default initial allocation for all subsequent SUB_HEAPs USHORT _cbInitAlloc; // Count number of times a new SUB_HEAP could not be created ULONG _cExpandErrors; // Allocation behavior control word USHORT _fsBehave; // Add a new SUB_HEAP and allocate from it. virtual BYTE * GrowAndAlloc( USHORT cbBytes, USHORT fsFlags = 0 ); // parameterless initialization used by MEM_MASTER GIANT_HEAP(); public: // Public constructor for additional GIANT_HEAPs GIANT_HEAP( USHORT cbInitialAllocation ); ~GIANT_HEAP(); BOOL SetBehavior( USHORT fFlag, BOOL fOnOff ); BOOL SetDeleteOnEmpty ( BOOL fDelete ) { return SetBehavior( GHbDelete, fDelete ); } BOOL SetExtendOnFull ( BOOL fExtend ) { return SetBehavior( GHbExtend, fExtend ); } BOOL SetResizeOnEmpty ( BOOL fResize ) { return SetBehavior( GHbResize, fResize ); } ULONG QueryExpandErrors() { return _cExpandErrors ; } // Return a pointer to the newest SUB_HEAP in the ensemble. SUB_HEAP * QueryLatest(); virtual BYTE * Alloc( USHORT cbBytes, USHORT fsFlags = 0 ); virtual BOOL Free( BYTE * pbBlock ); virtual ULONG CalcDeallocErrors(); virtual ULONG QueryTotalBlocks(); }; /************************************************************************* NAME: MEM_MASTER SYNOPSIS: MEM_MASTER serves primarily as the anchor for the linked list of SUB_HEAPS and the locus of the global "new" and "delete" operators. It also maintains a pointer to the current "focussed" GIANT_HEAP. As explained in HEAPBIG.CXX, before instantiation, the global "new" and "delete" operators simply use LocalAlloc and LocalFree. After instantiation of MEM_MASTER (via "Init"), MEM_MASTER is created as a GIANT_HEAP which covers the local, DS-relative heap. Instantiation also creates the first instance of a GIANT_HEAP, which implies that the first SUB_HEAP is also created. The effect is two-fold. First, a GIANT_HEAP is ready for use, and allocates memory obtained through GlobalAlloc. Second, the MEM_MASTER is still available as a GIANT_HEAP in case the uses wishes to temporarily allocate from the local heap. MEM_MASTER is the first instance both of a SUB_HEAP and a GIANT_HEAP. It can be distinguished from other HEAPs because: 1) it's a GIANT_HEAP, since _pOwner == this (self), and 2) this (self) == _pmmInstance, it's the one and only MEM_MASTER. INTERFACE: Call MEM_MASTER::Init(). This creates the sole, global instance of a MEM_MASTER, _pmmInstance. After Init(), all "new" and "delete" operations will automatically flow through _pmmInstance. Init() - initialize InitForDll() - initialize for DLL Term() - terminate Alloc() - allocate Free() - free QueryBlockSize() - size of the block SetFocus() - refocus on the subheap GetGiantFocus() - get giant focus QueryTotalHeaps() - Total heaps QueryTotalBlocks() - total blocks PARENT: GIANT_HEAP USES: SUB_HEAP CAVEATS: See SUB_HEAP, CAVEATS. Warning about InitForDll: Under Windows, memory allocated by a DLL is always "owned" by the active task which invoked the DLL. The InitForDll method is primarily intended for LANMAN.DRV, which is loaded by the Window's shell and not unloaded until Windows is terminated. Calling InitForDll preallocates several heaps and prevents further expansion. Thus, all the memory used will belong to the shell, which first loaded LANMAN.DRV. This technique WILL NOT WORK for normal DLL usage. NOTES: Normally, usage is indirect. Intended use is through the global replacement "new" and "delete" operators. In other words, if you link HEAPBIG.CXX into your program, you only have to call MEM_MASTER::Init. HISTORY: DavidHov 2-25-91 Created **************************************************************************/ DLL_CLASS MEM_MASTER : public GIANT_HEAP { private: // This may point to a SUB_HEAP or a GIANT_HEAP SUB_HEAP * _pFocus; virtual BYTE * GrowAndAlloc( USHORT cbBytes, USHORT fsFlags = 0 ); // De/constructor MEM_MASTER( USHORT cbInitAlloc ); ~MEM_MASTER(); public: static BOOL Init(); static BOOL InitForDll ( INT cPreallocHeaps ); static BOOL Term(); // Primary methods used by global "new" and "delete". virtual BYTE * Alloc ( USHORT cbBytes, USHORT fsFlags = 0 ); virtual BOOL Free ( BYTE * pbBlock ); // Return the size of any previously allocated block. USHORT QueryBlockSize( BYTE * pbBlock ); // Change the GIANT_HEAP in use. BOOL SetFocus( SUB_HEAP * pSubHeap ); // Returns the focussed GIANT_HEAP or NULL GIANT_HEAP * GetGiantFocus(); // Returns the focussed SUB_HEAP or NULL SUB_HEAP * GetSubFocus(); USHORT QueryTotalHeaps(); ULONG QueryTotalBlocks(); // Check the health of the heap BOOL Walk () ; }; #endif // !Win32 #endif // _HEAP_HXX_