This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
nekohook/modules/source2013/sdk/public/tier1/utlobjectreference.h
2020-08-04 13:13:01 -04:00

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