windows-nt/Source/XPSP1/NT/admin/activec/inc/refcount.h
2020-09-26 16:20:57 +08:00

258 lines
5.4 KiB
C++

/*--------------------------------------------------------------------------*
*
* Microsoft Windows
* Copyright (C) Microsoft Corporation, 1992 - 1999
*
* File: refcount.h
*
* Contents: Interface file for reference counting templates
*
* History: 05-Oct-98 jeffro Created
*
*--------------------------------------------------------------------------*/
#ifndef REFCOUNT_H
#define REFCOUNT_H
#pragma once
#include "stddbg.h"
template<class T> class CRefCountedObject;
template<class T> class CRefCountedPtr;
/*+-------------------------------------------------------------------------*
* CRefCountedObject
*
* Template reference-counted object class, intended to be used in
* conjuction with CRefCountedPtr<T>.
*
* Typically, you'd use this like so:
*
* class CClassWithoutRefCounting;
* typedef CRefCountedObject<CClassWithoutRefCounting> CClassWithRefCounting;
*
* CClassWithRefCounting::SmartPtr m_spClass;
* m_spClass.CreateInstance ();
*--------------------------------------------------------------------------*/
template<class BaseClass>
class CRefCountedObject : public BaseClass
{
public:
typedef CRefCountedObject<BaseClass> ThisClass;
typedef CRefCountedPtr<ThisClass> SmartPtr;
CRefCountedObject () : m_cRefs (0) {}
private:
/*
* CRefCountedObject's should only be created on the heap,
* so we'll protect the dtor so it can only be deleted from
* Release, not by automatic object unwinding
*/
~CRefCountedObject () {}
public:
static ThisClass* CreateInstance ()
{
return (new ThisClass);
}
LONG AddRef()
{
return (InterlockedIncrement (&m_cRefs));
}
LONG Release()
{
/*
* if this assert fails, we have mismatched AddRef/Release's
*/
ASSERT (m_cRefs > 0);
LONG rc = InterlockedDecrement (&m_cRefs);
if (rc == 0)
delete this;
return (rc);
}
LONG m_cRefs;
private:
/*
* CRefCountedObject's are not meant to be copied or assigned
*/
CRefCountedObject (const CRefCountedObject& other); // no impl
CRefCountedObject& operator= (const CRefCountedObject& other); // no impl
};
/*+-------------------------------------------------------------------------*
* CRefCountedPtr
*
* Template reference-counted smart pointer class, intended to be used in
* conjuction with CRefCountedObject<T>.
*
* T must implement CreateInstance, AddRef and Release. It can do this
* intrisically, or use the implementation in CRefCountedObject like this:
*
* class CClassWithoutRefCounting;
* typedef CRefCountedObject<CClassWithoutRefCounting> CClassWithRefCounting;
*--------------------------------------------------------------------------*/
template<class T>
class CRefCountedPtr
{
public:
CRefCountedPtr (T* pRealObject = NULL) :
m_pRealObject (pRealObject)
{
SafeAddRef();
}
CRefCountedPtr (const CRefCountedPtr<T>& other) :
m_pRealObject (other.m_pRealObject)
{
SafeAddRef();
}
~CRefCountedPtr ()
{
SafeRelease();
}
T* operator->() const
{
return (m_pRealObject);
}
operator T*() const
{
return (m_pRealObject);
}
T& operator*() const
{
return (*m_pRealObject);
}
T** operator&()
{
ASSERT (m_pRealObject == NULL);
return (&m_pRealObject);
}
CRefCountedPtr<T>& operator= (const CRefCountedPtr<T>& other)
{
return (operator= (other.m_pRealObject));
}
CRefCountedPtr<T>& operator= (T* pOtherObject)
{
if (pOtherObject != m_pRealObject)
{
T* pOldObject = m_pRealObject;
m_pRealObject = pOtherObject;
SafeAddRef();
if (pOldObject != NULL)
pOldObject->Release();
}
return (*this);
}
bool CreateInstance()
{
SafeRelease();
m_pRealObject = T::CreateInstance();
if (m_pRealObject == NULL)
return (false);
m_pRealObject->AddRef();
return (true);
}
LONG AddRef()
{
return (SafeAddRef());
}
LONG Release()
{
LONG cRefs = SafeRelease();
m_pRealObject = NULL;
return (cRefs);
}
void Attach(T* pNewObject)
{
if (pNewObject != m_pRealObject)
{
SafeRelease();
m_pRealObject = pNewObject;
}
}
T* Detach()
{
T* pOldObject = m_pRealObject;
m_pRealObject = NULL;
return (pOldObject);
}
bool operator!() const
{
return (m_pRealObject == NULL);
}
bool operator==(const CRefCountedPtr<T>& other)
{
return (m_pRealObject == other.m_pRealObject);
}
bool operator!=(const CRefCountedPtr<T>& other)
{
return (m_pRealObject != other.m_pRealObject);
}
/*
* for comparison to NULL
*/
bool operator==(int null) const
{
ASSERT (null == 0);
return (m_pRealObject == NULL);
}
bool operator!=(int null) const
{
ASSERT (null == 0);
return (m_pRealObject != NULL);
}
protected:
LONG SafeAddRef ()
{
return ((m_pRealObject) ? m_pRealObject->AddRef() : 0);
}
LONG SafeRelease ()
{
return ((m_pRealObject) ? m_pRealObject->Release() : -1);
}
protected:
T* m_pRealObject;
};
#endif /* REFCOUNT_H */