windows-nt/Source/XPSP1/NT/base/cluster/mgmt/inc/smartclasses.h
2020-09-26 16:20:57 +08:00

702 lines
17 KiB
C++

/////////////////////////////////////////////////////////////////////////////
//
// 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 <unknwn.h>
/////////////////////////////////////////////////////////////////////////////
// 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 )