diff options
Diffstat (limited to 'public/tier1/smartptr.h')
| -rw-r--r-- | public/tier1/smartptr.h | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/public/tier1/smartptr.h b/public/tier1/smartptr.h new file mode 100644 index 0000000..466ca0b --- /dev/null +++ b/public/tier1/smartptr.h @@ -0,0 +1,279 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef SMARTPTR_H +#define SMARTPTR_H +#ifdef _WIN32 +#pragma once +#endif + + +class CRefCountAccessor +{ +public: + template< class T > + static void AddRef( T *pObj ) + { + pObj->AddRef(); + } + + template< class T > + static void Release( T *pObj ) + { + pObj->Release(); + } +}; + +// This can be used if your objects use AddReference/ReleaseReference function names. +class CRefCountAccessorLongName +{ +public: + template< class T > + static void AddRef( T *pObj ) + { + pObj->AddReference(); + } + + template< class T > + static void Release( T *pObj ) + { + pObj->ReleaseReference(); + } +}; + + +// +// CPlainAutoPtr +// is a smart wrapper for a pointer on the stack that performs "delete" upon destruction. +// +// No reference counting is performed, copying is prohibited "s_p2.Attach( s_p1.Detach() )" should be used +// for readability and ease of maintenance. +// +// Auto pointer supports an "arrow" operator for invoking methods on the pointee and a "dereference" operator +// for getting a pointee reference. +// +// No automatic casting to bool/ptrtype is performed to avoid bugs and problems (read on "safe bool idiom" +// if casting to bool or pointer happens to be useful). +// +// Test for validity with "IsValid", get the pointer with "Get". +// +template < typename T > +class CPlainAutoPtr +{ +public: + explicit CPlainAutoPtr( T *p = NULL ) : m_p( p ) {} + ~CPlainAutoPtr( void ) { Delete(); } + +public: + void Delete( void ) { delete Detach(); } + +private: // Disallow copying, use Detach() instead to avoid ambiguity + CPlainAutoPtr( CPlainAutoPtr const &x ); + CPlainAutoPtr & operator = ( CPlainAutoPtr const &x ); + +public: + void Attach( T *p ) { m_p = p; } + T * Detach( void ) { T * p( m_p ); m_p = NULL; return p; } + +public: + bool IsValid( void ) const { return m_p != NULL; } + T * Get( void ) const { return m_p; } + T * operator -> ( void ) const { return Get(); } + T & operator * ( void ) const { return *Get(); } + +private: + T * m_p; +}; + +// +// CArrayAutoPtr +// is a smart wrapper for an array pointer on the stack that performs "delete []" upon destruction. +// +// No reference counting is performed, copying is prohibited "s_p2.Attach( s_p1.Detach() )" should be used +// for readability and ease of maintenance. +// +// Auto pointer supports an "indexing" operator for accessing array elements. +// +// No automatic casting to bool/ptrtype is performed to avoid bugs and problems (read on "safe bool idiom" +// if casting to bool or pointer happens to be useful). +// +// Test for validity with "IsValid", get the array pointer with "Get". +// +template < typename T > +class CArrayAutoPtr : public CPlainAutoPtr < T > // Warning: no polymorphic destructor (delete on base class will be a mistake) +{ +public: + explicit CArrayAutoPtr( T *p = NULL ) { this->Attach( p ); } + ~CArrayAutoPtr( void ) { this->Delete(); } + +public: + void Delete( void ) { delete [] CPlainAutoPtr < T >::Detach(); } + +public: + T & operator [] ( int k ) const { return CPlainAutoPtr < T >::Get()[ k ]; } +}; + + +// Smart pointers can be used to automatically free an object when nobody points +// at it anymore. Things contained in smart pointers must implement AddRef and Release +// functions. If those functions are private, then the class must make +// CRefCountAccessor a friend. +template<class T, class RefCountAccessor=CRefCountAccessor> +class CSmartPtr +{ +public: + CSmartPtr(); + CSmartPtr( T *pObj ); + CSmartPtr( const CSmartPtr<T,RefCountAccessor> &other ); + ~CSmartPtr(); + + T* operator=( T *pObj ); + void operator=( const CSmartPtr<T,RefCountAccessor> &other ); + const T* operator->() const; + T* operator->(); + bool operator!() const; + bool operator==( const T *pOther ) const; + bool IsValid() const; // Tells if the pointer is valid. + T* GetObject() const; // Get temporary object pointer, don't store it for later reuse! + void MarkDeleted(); + +private: + T *m_pObj; +}; + + +template< class T, class RefCountAccessor > +inline CSmartPtr<T,RefCountAccessor>::CSmartPtr() +{ + m_pObj = NULL; +} + +template< class T, class RefCountAccessor > +inline CSmartPtr<T,RefCountAccessor>::CSmartPtr( T *pObj ) +{ + m_pObj = NULL; + *this = pObj; +} + +template< class T, class RefCountAccessor > +inline CSmartPtr<T,RefCountAccessor>::CSmartPtr( const CSmartPtr<T,RefCountAccessor> &other ) +{ + m_pObj = NULL; + *this = other; +} + +template< class T, class RefCountAccessor > +inline CSmartPtr<T,RefCountAccessor>::~CSmartPtr() +{ + if ( m_pObj ) + { + RefCountAccessor::Release( m_pObj ); + } +} + +template< class T, class RefCountAccessor > +inline T* CSmartPtr<T,RefCountAccessor>::operator=( T *pObj ) +{ + if ( pObj == m_pObj ) + return pObj; + + if ( pObj ) + { + RefCountAccessor::AddRef( pObj ); + } + if ( m_pObj ) + { + RefCountAccessor::Release( m_pObj ); + } + m_pObj = pObj; + return pObj; +} + +template< class T, class RefCountAccessor > +inline void CSmartPtr<T,RefCountAccessor>::MarkDeleted() +{ + m_pObj = NULL; +} + +template< class T, class RefCountAccessor > +inline void CSmartPtr<T,RefCountAccessor>::operator=( const CSmartPtr<T,RefCountAccessor> &other ) +{ + *this = other.m_pObj; +} + +template< class T, class RefCountAccessor > +inline const T* CSmartPtr<T,RefCountAccessor>::operator->() const +{ + return m_pObj; +} + +template< class T, class RefCountAccessor > +inline T* CSmartPtr<T,RefCountAccessor>::operator->() +{ + return m_pObj; +} + +template< class T, class RefCountAccessor > +inline bool CSmartPtr<T,RefCountAccessor>::operator!() const +{ + return !m_pObj; +} + +template< class T, class RefCountAccessor > +inline bool CSmartPtr<T,RefCountAccessor>::operator==( const T *pOther ) const +{ + return m_pObj == pOther; +} + +template< class T, class RefCountAccessor > +inline bool CSmartPtr<T,RefCountAccessor>::IsValid() const +{ + return m_pObj != NULL; +} + +template< class T, class RefCountAccessor > +inline T* CSmartPtr<T,RefCountAccessor>::GetObject() const +{ + return m_pObj; +} + + +// +// CAutoPushPop +// allows you to set value of a variable upon construction and destruction. +// Constructors: +// CAutoPushPop x( myvar ) +// saves the value and restores upon destruction. +// CAutoPushPop x( myvar, newvalue ) +// saves the value, assigns new value upon construction, restores saved value upon destruction. +// CAutoPushPop x( myvar, newvalue, restorevalue ) +// assigns new value upon construction, assignes restorevalue upon destruction. +// +template < typename T > +class CAutoPushPop +{ +public: + explicit CAutoPushPop( T& var ) : m_rVar( var ), m_valPop( var ) {} + CAutoPushPop( T& var, T const &valPush ) : m_rVar( var ), m_valPop( var ) { m_rVar = valPush; } + CAutoPushPop( T& var, T const &valPush, T const &valPop ) : m_rVar( var ), m_valPop( var ) { m_rVar = valPush; } + + ~CAutoPushPop() { m_rVar = m_valPop; } + +private: // forbid copying + CAutoPushPop( CAutoPushPop const &x ); + CAutoPushPop & operator = ( CAutoPushPop const &x ); + +public: + T & Get() { return m_rVar; } + +private: + T &m_rVar; + T m_valPop; +}; + + +#endif // SMARTPTR_H |