source-engine/public/tier1/utlobjectreference.h

166 lines
3.2 KiB
C
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// $Revision: $
// $NoKeywords: $
//===========================================================================//
#ifndef UTLOBJECTREFERENCE_H
#define UTLOBJECTREFERENCE_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlintrusivelist.h"
#include "mathlib/mathlib.h"
// Purpose: class for keeping track of all the references that exist to an object. When the object
// being referenced is freed, all of the references pointing at it will become null.
//
// To Use:
// Add a DECLARE_REFERENCED_CLASS to the class that you want to use CutlReferences with.
// Replace pointers to that class with CUtlReferences.
// Check these references for null in appropriate places.
//
// NOTE : You can still happily use pointers instead of references where you want to - these
// pointers will not magically become null like references would, but if you know no one is going
// to delete the underlying object during a partcular section of code, it doesn't
// matter. Basically, CUtlReferences don't rely on every use of an object using one.
template<class T> class CUtlReference
{
public:
FORCEINLINE CUtlReference(void)
{
m_pNext = m_pPrev = NULL;
m_pObject = NULL;
}
FORCEINLINE CUtlReference(T *pObj)
{
m_pNext = m_pPrev = NULL;
AddRef( pObj );
}
FORCEINLINE ~CUtlReference(void)
{
KillRef();
}
FORCEINLINE void Set(T *pObj)
{
if ( m_pObject != pObj )
{
KillRef();
AddRef( pObj );
}
}
FORCEINLINE T * operator()(void) const
{
return m_pObject;
}
FORCEINLINE operator T*()
{
return m_pObject;
}
FORCEINLINE operator const T*() const
{
return m_pObject;
}
FORCEINLINE T* operator->()
{
return m_pObject;
}
FORCEINLINE const T* operator->() const
{
return m_pObject;
}
FORCEINLINE CUtlReference &operator=( const CUtlReference& otherRef )
{
Set( otherRef.m_pObject );
return *this;
}
FORCEINLINE CUtlReference &operator=( T *pObj )
{
Set( pObj );
return *this;
}
FORCEINLINE bool operator==( const CUtlReference& o ) const
{
return ( o.m_pObject == m_pObject );
}
public:
CUtlReference *m_pNext;
CUtlReference *m_pPrev;
T *m_pObject;
FORCEINLINE void AddRef( T *pObj )
{
m_pObject = pObj;
if ( pObj )
{
pObj->m_References.AddToHead( this );
}
}
FORCEINLINE void KillRef(void)
{
if ( m_pObject )
{
m_pObject->m_References.RemoveNode( this );
m_pObject = NULL;
}
}
};
template<class T> class CUtlReferenceList : public CUtlIntrusiveDList< CUtlReference<T> >
{
public:
~CUtlReferenceList( void )
{
CUtlReference<T> *i = CUtlIntrusiveDList<CUtlReference<T> >::m_pHead;
while( i )
{
CUtlReference<T> *n = i->m_pNext;
i->m_pNext = NULL;
i->m_pPrev = NULL;
i->m_pObject = NULL;
i = n;
}
CUtlIntrusiveDList<CUtlReference<T> >::m_pHead = NULL;
}
};
//-----------------------------------------------------------------------------
// Put this macro in classes that are referenced by CUtlReference
//-----------------------------------------------------------------------------
#define DECLARE_REFERENCED_CLASS( _className ) \
private: \
CUtlReferenceList< _className > m_References; \
template<class T> friend class CUtlReference;
#endif