windows-nt/Source/XPSP1/NT/public/sdk/inc/refptrco.h
2020-09-26 16:20:57 +08:00

409 lines
8.5 KiB
C++

//***************************************************************************
//
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
//
// RefPtrCo.h
//
// Purpose: definition of TRefPointerCollection template
//
//***************************************************************************
#if _MSC_VER > 1000
#pragma once
#endif
#ifndef __REFPTRCOLLECTION_H__
#define __REFPTRCOLLECTION_H__
#include <chptrarr.h>
// Enumeration helpers
typedef DWORD REFPTRCOLLECTION_POSITION;
#define REFPTRCOLLECTION_START 0xFFFFFFFF;
template <class TYPED_PTR> class TRefPointerCollection : public CThreadBase
{
public:
// Construction/Destruction
TRefPointerCollection();
~TRefPointerCollection();
TRefPointerCollection(const TRefPointerCollection& trpc);
// Allows addition and enumeration of collection
BOOL Add( TYPED_PTR* ptr );
BOOL BeginEnum( REFPTRCOLLECTION_POSITION& pos );
TYPED_PTR* GetNext( REFPTRCOLLECTION_POSITION& pos );
void EndEnum( void );
void Empty( void );
int GetSize( void ) const;
protected:
// Allows easy and quick transference of data (it was =, but
// because we'll inherit classes off the template, we won't
// inherit that particular overload (some C++ thingie)
const TRefPointerCollection<TYPED_PTR>& Copy( const TRefPointerCollection<TYPED_PTR>& );
private:
CHPtrArray m_ptrArray;
};
////////////////////////////////////////////////////////////////////////
//
// Function: TRefPointerCollection::TRefPointerCollection
//
// Class Constructor.
//
// Inputs: None.
//
// Outputs: None.
//
// Return: None.
//
// Comments: None.
//
////////////////////////////////////////////////////////////////////////
template <class TYPED_PTR>
TRefPointerCollection<TYPED_PTR>::TRefPointerCollection( void )
: CThreadBase(),
m_ptrArray()
{
}
////////////////////////////////////////////////////////////////////////
//
// Function: CRefPointerCollection::~CRefPointerCollection
//
// Class Destructor.
//
// Inputs: None.
//
// Outputs: None.
//
// Return: None.
//
// Comments: None.
//
////////////////////////////////////////////////////////////////////////
template <class TYPED_PTR>
TRefPointerCollection<TYPED_PTR>::~TRefPointerCollection( void )
{
Empty();
}
////////////////////////////////////////////////////////////////////////
//
// Function: CRefPointerCollection::CRefPointerCollection
// Copy constructor
//
// Inputs: None.
//
// Outputs: None.
//
// Return: None.
//
// Comments: None.
//
////////////////////////////////////////////////////////////////////////
template <class TYPED_PTR>
TRefPointerCollection<TYPED_PTR>::TRefPointerCollection(
const TRefPointerCollection& trpc)
{
Copy(trpc);
}
////////////////////////////////////////////////////////////////////////
//
// Function: TRefPointerCollection::Add
//
// Adds a new referenced pointer to the collection.
//
// Inputs: T* ptr - Pointer to add.
//
// Outputs: None.
//
// Return: TRUE/FALSE Success/Failure of Add.
//
// Comments: AddRefs the pointer, then adds it to the array. We
// will need Write Access to do this.
//
////////////////////////////////////////////////////////////////////////
template <class TYPED_PTR>
BOOL TRefPointerCollection<TYPED_PTR>::Add( TYPED_PTR* ptr )
{
BOOL fReturn = FALSE;
if ( NULL != ptr )
{
// Get write access
if ( BeginWrite() )
{
try
{
// If Add succeeds, the pointer will be released when it
// is removed.
ptr->AddRef();
if ( m_ptrArray.Add( (void*) ptr ) >= 0 )
{
fReturn = TRUE;
}
else
{
ptr->Release(); // Add failed, so Release the AddRef
}
}
catch ( ... )
{
EndWrite() ;
throw;
}
EndWrite(); // Release the BeginWrite()
}
}
return fReturn;
}
////////////////////////////////////////////////////////////////////////
//
// Function: TRefPointerCollection::BeginEnum
//
// Gains Read Access to the collection, then returns an appropriate
// REFPTRCOLLECTION_POSITION to get the first index in the array.
//
// Inputs: None.
//
// Outputs: REFPTRCOLLECTION_POSITION& pos - Position we retrieved.
//
// Return: BOOL TRUE/FALSE - Access was granted
//
// Comments: We need Read Access to do this. This can effectively
// lock out other threads.
//
////////////////////////////////////////////////////////////////////////
template <class TYPED_PTR>
BOOL TRefPointerCollection<TYPED_PTR>::BeginEnum( REFPTRCOLLECTION_POSITION& pos )
{
BOOL fReturn = FALSE;
if ( BeginRead() )
{
pos = REFPTRCOLLECTION_START;
fReturn = TRUE;
}
return fReturn;
}
////////////////////////////////////////////////////////////////////////
//
// Function: TRefPointerCollection::EndEnum
//
// Signals the end of an enumeration.
//
// Inputs: None.
//
// Outputs: None.
//
// Return: BOOL TRUE/FALSE - Access was granted
//
// Comments: Ends Read Access granted by calling BeginEnum().
//
////////////////////////////////////////////////////////////////////////
template <class TYPED_PTR>
void TRefPointerCollection<TYPED_PTR>::EndEnum( void )
{
EndRead();
}
////////////////////////////////////////////////////////////////////////
//
// Function: TRefPointerCollection::GetNext
//
// Uses the REFPTRCOLLECTION_POSITION to get the next index in the
// collection.
//
// Inputs: None.
//
// Outputs: REFPTRCOLLECTION_POSITION& pos - Position we retrieved.
//
// Return: T* NULL if failure.
//
// Comments: We need Read Access to do this. The pointer is AddRef'd
// on the way out. User must Release the pointer himself.
//
////////////////////////////////////////////////////////////////////////
template <class TYPED_PTR>
TYPED_PTR* TRefPointerCollection<TYPED_PTR>::GetNext( REFPTRCOLLECTION_POSITION& pos )
{
TYPED_PTR* ptr = NULL;
if ( BeginRead() )
{
if ( ++pos < (DWORD) m_ptrArray.GetSize() )
{
ptr = (TYPED_PTR*) m_ptrArray.GetAt( pos );
if ( NULL != ptr )
{
ptr->AddRef();
}
}
EndRead();
}
return ptr;
}
////////////////////////////////////////////////////////////////////////
//
// Function: TRefPointerCollection::Empty
//
// Empties out the collection, Releasing Pointers as it does do.
//
// Inputs: None.
//
// Outputs: None.
//
// Return: None.
//
// Comments: We need Write Access to do this.
//
////////////////////////////////////////////////////////////////////////
template <class TYPED_PTR>
void TRefPointerCollection<TYPED_PTR>::Empty( void )
{
// By default this is an infinite wait, so it best come back
BeginWrite();
try
{
int nSize = m_ptrArray.GetSize();
// Only empty it if it is not empty
if ( nSize > 0 )
{
TYPED_PTR* ptr = NULL;
for ( int nCtr = 0; nCtr < nSize; nCtr++ )
{
ptr = (TYPED_PTR*) m_ptrArray[nCtr];
if ( NULL != ptr )
{
ptr->Release(); // AddRef we did when we added it
}
}
// Now dump the array
m_ptrArray.RemoveAll();
} // IF nSize > 0
}
catch ( ... )
{
EndWrite() ;
throw;
}
EndWrite();
}
////////////////////////////////////////////////////////////////////////
//
// Function: TRefPointerCollection::Copy
//
// Empties out the collection, copies in another one, addrefing
// pointers as we go.
//
// Inputs: const T& collection
//
// Outputs: None.
//
// Return: const T& this
//
// Comments: We need Write Access to do this.
//
////////////////////////////////////////////////////////////////////////
template <class TYPED_PTR>
const TRefPointerCollection<TYPED_PTR>& TRefPointerCollection<TYPED_PTR>::Copy( const TRefPointerCollection<TYPED_PTR>& collection )
{
// By default this is an infinite wait, so it best come back
BeginWrite();
try
{
// Dump out the array
Empty();
int nSize = collection.m_ptrArray.GetSize();
for ( int nCount = 0; nCount < nSize; nCount++ )
{
TYPED_PTR* ptr = (TYPED_PTR*) collection.m_ptrArray[nCount];
// Add will automatically AddRef the pointer again.
Add( ptr );
}
}
catch ( ... )
{
EndWrite() ;
throw;
}
EndWrite();
return *this;
}
////////////////////////////////////////////////////////////////////////
//
// Function: TRefPointerCollection::GetSize
//
// Inputs: None.
//
// Outputs: Number of elements in the collection
//
// Return: None.
//
// Comments: None.
//
////////////////////////////////////////////////////////////////////////
template <class TYPED_PTR>
int TRefPointerCollection<TYPED_PTR>::GetSize(void) const
{
return m_ptrArray.GetSize();
}
#endif