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.
2020-08-04 13:13:01 -04:00

270 lines
7.2 KiB
C++

//========= 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