#ifndef __SINGLETON_H__
#define __SINGLETON_H__
template < class Base >
class CComObjectSingleton : public Base
... {
public:
typedef Base _BaseClass;
typedef typename _BaseClass::_CritSec _CritSec;
CComObjectSingleton(void* = NULL)
...{
_Module.Lock();
}
// Set refcount to 1 to protect destruction
~CComObjectSingleton()
...{
m_dwRef = 1L;
FinalRelease();
#ifdef _ATL_DEBUG_INTERFACES
_Module.DeleteNonAddRefThunk(_GetRawUnknown());
#endif
_Module.Unlock();
}
//If InternalAddRef or InternalRelease is undefined then your class
//doesn't derive from CComObjectRoot
STDMETHOD_(ULONG, AddRef)() ...{return InternalAddRef();}
STDMETHOD_(ULONG, Release)()
...{
ULONG l;
s_critsec.Lock();
l = InternalRelease();
if (l == 0)
...{
s_pThis = NULL;
}
s_critsec.Unlock();
if (l == 0)
delete this;
return l;
}
//if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP
STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
...{return _InternalQueryInterface(iid, ppvObject);}
template <class Q>
HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp)
...{
return QueryInterface(__uuidof(Q), (void**)pp);
}
public:
static _CritSec s_critsec;
static _BaseClass* s_pThis;
} ;
template < class Base >
CComObjectSingleton < Base > ::_BaseClass *
CComObjectSingleton < Base > ::s_pThis = NULL;
template < class Base >
CComObjectSingleton < Base > ::_CritSec
CComObjectSingleton < Base > ::s_critsec;
template < class T1 >
class CComSingletonCreator
... {
public:
static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
...{
ATLASSERT(*ppv == NULL);
HRESULT hRes = E_OUTOFMEMORY;
T1* p = NULL;
T1::s_critsec.Lock();
if (T1::s_pThis != NULL)
...{
hRes = T1::s_pThis->QueryInterface(riid, ppv);
}
else
...{
ATLTRY(p = new T1(pv));
if (p != NULL)
...{
p->SetVoid(pv);
p->InternalFinalConstructAddRef();
hRes = p->FinalConstruct();
p->InternalFinalConstructRelease();
if (hRes == S_OK)
hRes = p->QueryInterface(riid, ppv);
if (hRes != S_OK)
delete p;
}
if (hRes == S_OK)
...{
T1::s_pThis = p;
}
}
T1::s_critsec.Unlock();
return hRes;
}
} ;
#define DECLARE_SINGLETON(x) public:
typedef CComCreator2 < CComSingletonCreator < CComObjectSingleton < x > > , CComFailCreator < CLASS_E_NOAGGREGATION > > _CreatorClass;
#endif // __SINGLETON_H__
#define __SINGLETON_H__
template < class Base >
class CComObjectSingleton : public Base
... {
public:
typedef Base _BaseClass;
typedef typename _BaseClass::_CritSec _CritSec;
CComObjectSingleton(void* = NULL)
...{
_Module.Lock();
}
// Set refcount to 1 to protect destruction
~CComObjectSingleton()
...{
m_dwRef = 1L;
FinalRelease();
#ifdef _ATL_DEBUG_INTERFACES
_Module.DeleteNonAddRefThunk(_GetRawUnknown());
#endif
_Module.Unlock();
}
//If InternalAddRef or InternalRelease is undefined then your class
//doesn't derive from CComObjectRoot
STDMETHOD_(ULONG, AddRef)() ...{return InternalAddRef();}
STDMETHOD_(ULONG, Release)()
...{
ULONG l;
s_critsec.Lock();
l = InternalRelease();
if (l == 0)
...{
s_pThis = NULL;
}
s_critsec.Unlock();
if (l == 0)
delete this;
return l;
}
//if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP
STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
...{return _InternalQueryInterface(iid, ppvObject);}
template <class Q>
HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp)
...{
return QueryInterface(__uuidof(Q), (void**)pp);
}
public:
static _CritSec s_critsec;
static _BaseClass* s_pThis;
} ;
template < class Base >
CComObjectSingleton < Base > ::_BaseClass *
CComObjectSingleton < Base > ::s_pThis = NULL;
template < class Base >
CComObjectSingleton < Base > ::_CritSec
CComObjectSingleton < Base > ::s_critsec;
template < class T1 >
class CComSingletonCreator
... {
public:
static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
...{
ATLASSERT(*ppv == NULL);
HRESULT hRes = E_OUTOFMEMORY;
T1* p = NULL;
T1::s_critsec.Lock();
if (T1::s_pThis != NULL)
...{
hRes = T1::s_pThis->QueryInterface(riid, ppv);
}
else
...{
ATLTRY(p = new T1(pv));
if (p != NULL)
...{
p->SetVoid(pv);
p->InternalFinalConstructAddRef();
hRes = p->FinalConstruct();
p->InternalFinalConstructRelease();
if (hRes == S_OK)
hRes = p->QueryInterface(riid, ppv);
if (hRes != S_OK)
delete p;
}
if (hRes == S_OK)
...{
T1::s_pThis = p;
}
}
T1::s_critsec.Unlock();
return hRes;
}
} ;
#define DECLARE_SINGLETON(x) public:
typedef CComCreator2 < CComSingletonCreator < CComObjectSingleton < x > > , CComFailCreator < CLASS_E_NOAGGREGATION > > _CreatorClass;
#endif // __SINGLETON_H__
用法:
class ATL_NO_VTABLE CTest:
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CTest, &CLSID_GUID>,
{
public:
DECLARE_SINGLETON(CTest)
}