//*************************************************************************** // // Copyright © 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 // Enumeration helpers typedef DWORD REFPTRCOLLECTION_POSITION; #define REFPTRCOLLECTION_START 0xFFFFFFFF; template 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& Copy( const TRefPointerCollection& ); private: CHPtrArray m_ptrArray; }; //////////////////////////////////////////////////////////////////////// // // Function: TRefPointerCollection::TRefPointerCollection // // Class Constructor. // // Inputs: None. // // Outputs: None. // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// template TRefPointerCollection::TRefPointerCollection( void ) : CThreadBase(), m_ptrArray() { } //////////////////////////////////////////////////////////////////////// // // Function: CRefPointerCollection::~CRefPointerCollection // // Class Destructor. // // Inputs: None. // // Outputs: None. // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// template TRefPointerCollection::~TRefPointerCollection( void ) { Empty(); } //////////////////////////////////////////////////////////////////////// // // Function: CRefPointerCollection::CRefPointerCollection // Copy constructor // // Inputs: None. // // Outputs: None. // // Return: None. // // Comments: None. // //////////////////////////////////////////////////////////////////////// template TRefPointerCollection::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 BOOL TRefPointerCollection::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 BOOL TRefPointerCollection::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 void TRefPointerCollection::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 TYPED_PTR* TRefPointerCollection::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 void TRefPointerCollection::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 const TRefPointerCollection& TRefPointerCollection::Copy( const TRefPointerCollection& 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 int TRefPointerCollection::GetSize(void) const { return m_ptrArray.GetSize(); } #endif