Skip to content

Instantly share code, notes, and snippets.

@dranger003
Created October 19, 2015 00:53
Show Gist options
  • Save dranger003/6abaab935bfd01fc9000 to your computer and use it in GitHub Desktop.
Save dranger003/6abaab935bfd01fc9000 to your computer and use it in GitHub Desktop.
// RefObj.h : includes CRefObject, CRefAutoPtr
//
// Written by "Daniel Ranger" <[email protected]>
// Copyright (c) 2009 Daniel Ranger
//
// DESCRIPTION
//
// CRefAutoPtr is a smart pointer class to manage reference count within
// a CRefObject class. A normal smart pointer class manages reference
// count within its own class however in this implementation you must
// "extend" an existing object with CRefObject so it can be used by a
// CRefAutoPtr. Here is an example of its use:
//
// class TExisting
// {
// ...
// };
//
// VOID SomeFunc(LPVOID pvParam)
// {
// CRefAutoPtr<TExisting> sp((CRefObject<TExisting>*)pvParam);
// ...
// }
//
// CRefObject<TExisting>* p =
// CRefObject<TExisting>::CreateInstance(/* TExisting ctor args */);
// CRefAutoPtr<TExisting> sp(p);
// SomeFunc(&sp); // or SomeFunc(sp); both are the same
//
// LICENSE
//
// This is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, at version 3 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef __REFOBJ_H__
#define __REFOBJ_H__
#pragma once
#ifndef ATLASSERT
#define ATLASSERT(expr) _ASSERTE(expr)
#endif // ATLASSERT
template<typename T>
class CRefAutoPtr;
template<typename TBase, typename TActivator>
class CRefObject;
// CRefActivatorTraits
/////////////////////////////////////////////////////////////////////////////
template<typename TBase>
class CRefActivatorTraits
{
typedef CRefObject<TBase, CRefActivatorTraits> T;
public:
static T* Create()
{ return new T(); }
template<typename T1>
static T* Create(T1 p1)
{ return new T(p1); }
template<typename T1, typename T2>
static T* Create(T1 p1, T2 p2)
{ return new T(p1, p2); }
template<typename T1, typename T2, typename T3>
static T* Create(T1 p1, T2 p2, T3 p3)
{ return new T(p1, p2, p3); }
template<typename T1, typename T2, typename T3, typename T4>
static T* Create(T1 p1, T2 p2, T3 p3, T4 p4)
{ return new T(p1, p2, p3, p4); }
template<typename T1, typename T2, typename T3, typename T4, typename T5>
static T* Create(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
{ return new T(p1, p2, p3, p4, p5); }
static VOID Destroy(T* p)
{ delete p; }
};
// CRefObject
/////////////////////////////////////////////////////////////////////////////
template<typename TBase, typename TActivator = CRefActivatorTraits<TBase>>
class CRefObject : public TBase
{
friend TActivator;
template<typename T>
friend class CRefAutoPtr;
private:
CRefObject()
{
_Init();
}
explicit CRefObject(const CRefObject& o)
{
_Init(o.m_lRefCount);
}
template<typename T1>
CRefObject(T1 p1) :
TBase(p1)
{
_Init();
}
template<typename T1, typename T2>
CRefObject(T1 p1, T2 p2) :
TBase(p1, p2)
{
_Init();
}
template<typename T1, typename T2, typename T3>
CRefObject(T1 p1, T2 p2, T3 p3) :
TBase(p1, p2, p3)
{
_Init();
}
template<typename T1, typename T2, typename T3, typename T4>
CRefObject(T1 p1, T2 p2, T3 p3, T4 p4) :
TBase(p1, p2, p3, p4)
{
_Init();
}
template<typename T1, typename T2, typename T3, typename T4, typename T5>
CRefObject(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) :
TBase(p1, p2, p3, p4, p5)
{
_Init();
}
public:
static CRefObject* CreateInstance()
{
return TActivator::Create();
}
template<typename T1>
static CRefObject* CreateInstance(T1 p1)
{
return TActivator::Create(p1);
}
template<typename T1, typename T2>
static CRefObject* CreateInstance(T1 p1, T2 p2)
{
return TActivator::Create(p1, p2);
}
template<typename T1, typename T2, typename T3>
static CRefObject* CreateInstance(T1 p1, T2 p2, T3 p3)
{
return TActivator::Create(p1, p2, p3);
}
template<typename T1, typename T2, typename T3, typename T4>
static CRefObject* CreateInstance(T1 p1, T2 p2, T3 p3, T4 p4)
{
return TActivator::Create(p1, p2, p3, p4);
}
template<typename T1, typename T2, typename T3, typename T4, typename T5>
static CRefObject* CreateInstance(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
{
return TActivator::Create(p1, p2, p3, p4, p5);
}
ULONG AddRef()
{
return ::InterlockedIncrement(&m_lRefCount);
}
ULONG Release()
{
LONG lCount = ::InterlockedDecrement(&m_lRefCount);
ATLASSERT(lCount >= 0);
if (lCount == 0)
TActivator::Destroy(this);
return lCount;
}
private:
VOID _Init(LONG lRefCount = 1)
{
m_lRefCount = lRefCount;
}
VOID _Swap(CRefObject& o)
{
_Swap(m_lRefCount, o.m_lRefCount);
}
template<typename T1, typename T2>
VOID _Swap(T1& p1, T2& p2)
{
T1 tmp = p1;
p1 = p2;
p2 = tmp;
}
public:
LONG m_lRefCount;
};
// CRefAutoPtr
/////////////////////////////////////////////////////////////////////////////
template<typename T>
class CRefAutoPtr
{
public:
CRefAutoPtr() throw() :
m_pT(NULL)
{ }
CRefAutoPtr(const CRefAutoPtr& sp) throw() :
m_pT(sp.m_pT)
{
_AddRef();
}
explicit CRefAutoPtr(CRefObject<T>* pT) throw() :
m_pT(NULL)
{
_Attach(pT);
}
virtual ~CRefAutoPtr() throw()
{
_Release();
}
CRefAutoPtr& operator =(const CRefAutoPtr& sp) throw()
{
_Release();
m_pT = sp.m_pT;
_AddRef();
return *this;
}
CRefObject<T>* operator &() throw()
{
_AddRef();
return m_pT;
}
operator CRefObject<T>*() throw()
{
return operator&();
}
CRefObject<T>* operator ->() const throw()
{
return m_pT;
}
bool operator !=(const CRefAutoPtr& sp) const throw()
{
return !operator==(sp);
}
bool operator ==(const CRefAutoPtr& sp) const throw()
{
return m_pT == sp.m_pT;
}
CRefObject<T>* Detach() throw()
{
CRefObject<T>* pT = m_pT;
m_pT = NULL;
return pT;
}
protected:
VOID _Attach(CRefObject<T>* pT) throw()
{
_Release();
m_pT = pT;
}
VOID _AddRef() throw()
{
CRefObject<T>* pT = m_pT;
if (pT)
pT->AddRef();
}
VOID _Release() throw()
{
CRefObject<T>* pT = m_pT;
if (pT)
{
m_pT = NULL;
pT->Release();
}
}
public:
CRefObject<T>* m_pT;
};
#endif // __REFOBJ_H__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment