///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000 Microsoft Corporation // // Module Name: // SmartClasses.h // // Description: // Definitions of "smart" classes used to make sure resources such as // memory and handles are deallocated or closed properly. // // Maintained By: // David Potter (DavidP) 08-SEP-1999 // Vij Vasu (Vvasu) 16-SEP-1999 // // Notes: // 1. These classes are functionally identical to version 3 of the // standard library's auto_ptr class. They are redefined here since this // version of auto_ptr has not yet found it's way into our build // environment. // // 2. These classes are not intended to be used as a base class. They are // meant to be space and time efficient wrappers. Using these as base // classes may require the use of virtual functions which will only make // their memory footprint larger. // // ///////////////////////////////////////////////////////////////////////////// // Make sure that this header is included only once #pragma once ///////////////////////////////////////////////////////////////////////////// // External Declarations ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // Include Files ///////////////////////////////////////////////////////////////////////////// #include ///////////////////////////////////////////////////////////////////////////// // Type Definitions ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // Constant Definitions ///////////////////////////////////////////////////////////////////////////// // Store the warning state. #pragma warning( push ) // Disable warning 4284. The text of the warning is below: // Return type for 'identifier::operator ->' is not a UDT or reference to a UDT. // Will produce errors if applied using infix notation #pragma warning( disable : 4284 ) ///////////////////////////////////////////////////////////////////////////// //++ // // class CSmartResource // // Description: // Automatically releases a resource. // // Template Arguments: // t_ResourceTrait // A class that provides functions and types needed this class. For example, // this class may have a function that is used to release the resource. // It must define the type of the resource. // // Remarks: // See Note 2 in the banner comment for this module. // //-- ///////////////////////////////////////////////////////////////////////////// template < class t_ResourceTrait > class CSmartResource { private: // // Private Types // typedef t_ResourceTrait::ResourceType ResourceType; // // Private Data // ResourceType m_hResource; public: // // Constructors & Destructors // // Default constructor explicit CSmartResource( ResourceType hResource = t_ResourceTrait::HGetNullValue() ) throw() : m_hResource( hResource ) { } //*** CSmartResource( ResourceType ) // Copy constructor CSmartResource( CSmartResource & rsrSourceInout ) throw() : m_hResource( rsrSourceInout.HRelinquishOwnership() ) { } //*** CSmartResource( CSmartResource & ) // Destructor ~CSmartResource() throw() { CloseRoutineInternal(); } //*** ~CSmartResource() // // Operators // // Assignment operator CSmartResource & operator=( CSmartResource & rsrRHSInout ) throw() { // Only perform the assignment if not assigning to self if ( &rsrRHSInout != this ) { CloseRoutineInternal(); m_hResource = rsrRHSInout.HRelinquishOwnership(); } // if: not assigning to self return *this; } //*** operator=() // Operator to cast to underlying resource type operator ResourceType( void ) const throw() { return m_hResource; } //*** operator ResourceType() // // Lightweight Access Methods // // Get the handle to the resource ResourceType HHandle( void ) const throw() { return m_hResource; } //*** HResource() // // Class Methods // // Determine if the resource handle is valid bool FIsInvalid( void ) const throw() { return ( m_hResource == t_ResourceTrait::HGetNullValue() ); } //*** FIsInvalid() // Assignment function CSmartResource & Assign( ResourceType hResource ) throw() { // Only perform the assignment if not assigning to self if ( m_hResource != hResource ) { CloseRoutineInternal(); m_hResource = hResource; } // if: not assigning to self return *this; } //*** Assign() // Free the resource. void Free( void ) throw() { CloseRoutineInternal(); m_hResource = t_ResourceTrait::HGetNullValue(); } //*** Free() // Relinquish ownership of the resouce without freeing it. ResourceType HRelinquishOwnership( void ) throw() { ResourceType hHandle = m_hResource; m_hResource = t_ResourceTrait::HGetNullValue(); return hHandle; } //*** HRelinquishOwnership() private: // // // Private operators // // The address-of operator CSmartResource * operator &() throw() { return this; } // // Private Class Methods // // Check and release the resource void CloseRoutineInternal( void ) throw() { if ( m_hResource != t_ResourceTrait::HGetNullValue() ) { t_ResourceTrait::CloseRoutine( m_hResource ); } // if: resource handle isn't invalid } //*** CloseRoutineInternal() }; //*** class CSmartResource ///////////////////////////////////////////////////////////////////////////// //++ // // class CPtrTrait // // Description: // Encapsulates the traits of pointers. // // Template Arguments: // t_Ty Type of memory to be managed (e.g. BYTE or int). // // Remarks: // See Note 2 in the banner comment for this module. // //-- ///////////////////////////////////////////////////////////////////////////// template < class t_Ty > class CPtrTrait { public: ////////////////////////////////////////////////////////////////////////// // Public types ////////////////////////////////////////////////////////////////////////// typedef t_Ty * ResourceType; typedef t_Ty DataType; ////////////////////////////////////////////////////////////////////////// // Public methods ////////////////////////////////////////////////////////////////////////// // A routine used to release a resource. static void CloseRoutine( ResourceType hResourceIn ) { delete hResourceIn; } //*** CloseRoutine() // Get the null value for this type. static ResourceType HGetNullValue() { return NULL; } //*** HGetNullValue() }; //*** class CPtrTrait ///////////////////////////////////////////////////////////////////////////// //++ // // class CArrayPtrTrait // // Description: // Encapsulates the traits of pointers. // // Template Arguments: // t_Ty Type of memory to be managed (e.g. BYTE or int). // // Remarks: // See Note 2 in the banner comment for this module. // //-- ///////////////////////////////////////////////////////////////////////////// template < class t_Ty > class CArrayPtrTrait { public: ////////////////////////////////////////////////////////////////////////// // Public types ////////////////////////////////////////////////////////////////////////// typedef t_Ty * ResourceType; typedef t_Ty DataType; ////////////////////////////////////////////////////////////////////////// // Public methods ////////////////////////////////////////////////////////////////////////// // A routine used to release a resource static void CloseRoutine( ResourceType hResourceIn ) { delete [] hResourceIn; } //*** CloseRoutine() // Get the null value for this type. static ResourceType HGetNullValue() { return NULL; } //*** HGetNullValue() }; //*** class CArrayPtrTrait ////////////////////////////////////////////////////////////////////////////// //++ // // class CHandleTrait // // Description: // The class is a handle trait class that can be used with handles whose // close routines take only one argument. // // t_Ty // Type of handle to be managed (e.g. HWND). // // t_CloseRoutineReturnType // The return type of the routine used to close the handle. // // t_CloseRoutine // The routine used to close the handle. This function cannot throw // exceptions. // // t_hNULL_VALUE // Null handle value. Defaults to NULL. // //-- ////////////////////////////////////////////////////////////////////////////// template < class t_Ty , class t_CloseRoutineReturnType , t_CloseRoutineReturnType (*t_CloseRoutine)( t_Ty hHandleIn ) throw() , t_Ty t_hNULL_VALUE = NULL > class CHandleTrait { public: ////////////////////////////////////////////////////////////////////////// // Public types ////////////////////////////////////////////////////////////////////////// typedef t_Ty ResourceType; ////////////////////////////////////////////////////////////////////////// // Public methods ////////////////////////////////////////////////////////////////////////// // A routine used to close a handle. static void CloseRoutine( ResourceType hResourceIn ) { t_CloseRoutine( hResourceIn ); } //*** CloseRoutine() // Get the null value for this type. static ResourceType HGetNullValue() { return t_hNULL_VALUE; } //*** HGetNullValue() }; //*** class CHandleTrait ///////////////////////////////////////////////////////////////////////////// //++ // // class CSmartGenericPtr // // Description: // Automatically handles deallocation of memory. // // Template Arguments: // t_PtrTrait // Trait class for the memory to be managed (e.g. CPtrTrait< int > ). // // Remarks: // See Note 2 in the banner comment for this module. // It is ok for this class to derive from CSmartResource since the // derivation is private and the lack of virtual functions will // therefore not cause any problems. // //-- ///////////////////////////////////////////////////////////////////////////// template < class t_PtrTrait > class CSmartGenericPtr : private CSmartResource< t_PtrTrait > { private: // // Private Types // typedef CSmartResource< t_PtrTrait > BaseClass; public: // // Public Types // typedef t_PtrTrait::DataType DataType; // // Constructors & Destructors // // Default and memory pointer constructor explicit CSmartGenericPtr( DataType * pMemIn = NULL ) throw() : BaseClass( pMemIn ) { } //*** CSmartGenericPtr( DataType * ) // Copy constructor CSmartGenericPtr( CSmartGenericPtr & rsrSourceInout ) throw() : m_pMem( rsrSourceInout.HRelinquishOwnership() ) { } //*** CSmartGenericPtr( CSmartGenericPtr & ) // Destructor ~CSmartGenericPtr( void ) throw() { } //*** ~CSmartGenericPtr() // // Operators // // Assignment operator CSmartGenericPtr & operator=( CSmartGenericPtr & rapRHSInout ) throw() { return static_cast< CSmartGenericPtr & >( BaseClass::operator=( rapRHSInout ) ); } //*** operator=() // Assign a pointer CSmartGenericPtr & Assign( DataType * pMemIn ) throw() { return static_cast< CSmartGenericPtr & >( BaseClass::Assign( pMemIn ) ); } //*** Assign() // Pointer dereference operator* DataType & operator*( void ) const throw() { return *HHandle(); } //*** operator*() // Pointer dereference operator-> DataType * operator->( void ) const throw() { return HHandle(); } //*** operator->() // // Lightweight Access Methods // // Get the memory pointer DataType * PMem( void ) const throw() { return HHandle(); } //*** PMem() // // Class Methods // // Determine if memory pointer is valid bool FIsEmpty( void ) const throw() { return FIsInvalid(); } //*** FIsEmpty() // Relinquish our ownership of the memory pointer DataType * PRelease( void ) throw() { return HRelinquishOwnership(); } //*** PRelease() }; //*** class CSmartGenericPtr ///////////////////////////////////////////////////////////////////////////// //++ // // class CSmartIfacePtr // // Description: // Automatically calls AddRef on creation and Release on destruction. // // Template Arguments: // t_Ty Type of pointer to be managed (e.g. IUnknown *). // // Remarks: // This class does not have the destructive copy semantics. That is, // when a CSmartIfacePtr object is copied, the source is still valid. // // See Note 2 in the banner comment for this module. // //-- ///////////////////////////////////////////////////////////////////////////// template < class t_Ty > class CSmartIfacePtr { private: // // Private Data // t_Ty * m_pUnk; public: // Class to prevent explicit calls to AddRef() and Release class INoAddRefRelease : public t_Ty { private: virtual ULONG STDMETHODCALLTYPE AddRef() = 0; virtual ULONG STDMETHODCALLTYPE Release() = 0; }; // // Constructors & Destructors // // Default and pointer constructor CSmartIfacePtr( t_Ty * pUnkIn = NULL ) throw() : m_pUnk( pUnkIn ) { AddRefInternal(); } //*** CSmartIfacePtr( t_Ty * ) // Copy constructor CSmartIfacePtr( const CSmartIfacePtr & rsrSourceIn ) throw() : m_pUnk( rsrSourceIn.PUnk() ) { AddRefInternal(); } //*** CSmartIfacePtr( CSmartIfacePtr & ) // Destructor ~CSmartIfacePtr( void ) throw() { ReleaseInternal(); } //*** ~CSmartIfacePtr() // // Operators // // Assignment operator INoAddRefRelease & operator=( const CSmartIfacePtr & rapRHSIn ) throw() { return Assign( rapRHSIn.PUnk() ); } //*** operator=() // Pointer dereference operator* INoAddRefRelease & operator*( void ) const throw() { return *( static_cast< INoAddRefRelease * >( m_pUnk ) ); } //*** operator*() // Pointer dereference operator-> INoAddRefRelease * operator->( void ) const throw() { return static_cast< INoAddRefRelease * >( m_pUnk ); } //*** operator->() // // Lightweight Access Methods // // Get the pointer INoAddRefRelease * PUnk( void ) const throw() { return static_cast< INoAddRefRelease * >( m_pUnk ); } //*** PUnk() // // Class Methods // // Assignment function. INoAddRefRelease & Assign( t_Ty * pRHSIn ) throw() { // Only perform the assignment if not assigning to self if ( pRHSIn != m_pUnk ) { ReleaseInternal(); m_pUnk = pRHSIn; AddRefInternal(); } // if: not assigning to self return *( static_cast< INoAddRefRelease * >( m_pUnk ) ); } //*** Assign() // Attach ( assign without AddRef() ) void Attach( t_Ty * pRHSIn ) throw() { // Only perform the attachment if not attaching to self if ( pRHSIn != m_pUnk ) { ReleaseInternal(); m_pUnk = pRHSIn; } // if: not attaching to self } //*** Attach() // Release this interface pointer. void Release() throw() { ReleaseInternal(); m_pUnk = NULL; } // Query punkSrc for __uuidof( m_pUnk ) and store the result. HRESULT HrQueryAndAssign( IUnknown * punkSrc ) throw() { ReleaseInternal(); return punkSrc->QueryInterface< t_Ty >( &m_pUnk ); } ///*** HrQueryAndAssign() // Determine if pointer is valid bool FIsEmpty( void ) const throw() { return ( m_pUnk == NULL ); } //*** FIsEmpty() private: // // // Private operators // // The address-of operator CSmartIfacePtr * operator &() { return this; } // // Private Class Methods // // Increment the reference count on the pointer void AddRefInternal( void ) throw() { if ( m_pUnk != NULL ) { m_pUnk->AddRef(); } } //*** PRelease() // Release the pointer. // A call to this function is usually be followed by a reassignment, or else // this will object may contain an invalid pointer. void ReleaseInternal( void ) throw() { if ( m_pUnk != NULL ) { m_pUnk->Release(); } } //*** PRelease() }; //*** class CSmartIfacePtr // Restore the warning state. #pragma warning( pop )