125 lines
3.5 KiB
C++
125 lines
3.5 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// $Revision: $
|
|
// $NoKeywords: $
|
|
//===========================================================================//
|
|
|
|
#ifndef UTLOBJECTREFERENCE_H
|
|
#define UTLOBJECTREFERENCE_H
|
|
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#include "mathlib/mathlib.h"
|
|
#include "tier1/utlintrusivelist.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
|