SweetDream
高歌一壶新酿酒,醉抱青山不必归。

今日在网上看到另一个Singleton的实现方式:和Ogre的那种比起来有如下好处:
1.使用了auto_ptr自动释放Singleton类。
2.解决多线程冲突。




------------------------------目录------------------------------
本文的主要内容为:
1、Singleton模式的基类
2、基本的Singleton容器
3、Singleton模板
4、引入线程保护代码
5、完整的代码
6、如何使用

------------------------------Singleton模式的基类------------------------------
1、Singleton模式的基类
首 先需要统一Singleton类家族的风格,我们用宏定义全权实现构造函数、析构函数和静态的GetInstance()函数。但每一个 Singleton也许有其自己的个性,在构造和析构的时候,可能会有额外的操作,我们将其延伸至以下两个纯虚函数中来,由每个Singleton类自己 去完成。
class SinglePattern
{
protected:
virtual void InitialInstance() = 0;
virtual void DisposeInstance() = 0;
};

------------------------------基本的Singleton容器------------------------------
2、基本的Singleton容器
我们使用auto_ptr来管理指针,使之在程序结束时会正确的得到析构。
以下为基本的一个Singleton容器,其所容指针即为自己的一个实例。
class Singleton
{
friend class auto_ptr<Singleton>;
protected:
static auto_ptr<Singleton> m_Instance;
protected:
__fastcall Singleton(){};
virtual ~Singleton(){};
public:
static Singleton* __fastcall GetInstance()
{
if(m_Instance.get() == NULL)
{
m_Instance.reset(new Singleton());
}
return m_Instance.get();
}
};
auto_ptr<Singleton> Singleton::m_Instance;

------------------------------Singleton模板------------------------------
3、Singleton模板
如果我们对每一个Singleton类都向上面所写那样,我们需要做很多重复工作。现在我们使用模板类来包装一下。
我们只需要将上面的代码,用auto_ptr管理的指针改成模板代码即可,程序代码如下:
template <class T>
class Singleton
{
friend class auto_ptr<T>;
protected:
static auto_ptr<T> m_Instance;
protected:
__fastcall Singleton(){};
virtual ~Singleton(){};
public:
static T* __fastcall GetInstance()
{
if(m_Instance.get() == NULL)
{
m_Instance.reset(new T());
}
return m_Instance.get();
}
};
template<class T>
auto_ptr<T> Singleton<T>::m_Instance;

实际上你可以看见,如果编写Singleton<Singleton>即变成了基本的Singleton。

------------------------------引入线程保护代码------------------------------
4、引入线程保护代码
上面的代码在单线程中可以很好的工作,但在多线程环境中,会产生实例被析构再构造的假Singleton类。这里我只引入一个简单的线程保护代码做个示例:
class CResGuard
{
public:
CResGuard() { m_lGrdCnt = 0; InitializeCriticalSection(&m_cs); }
~CResGuard() { DeleteCriticalSection(&m_cs); }
// IsGuarded is used for debugging
BOOL IsGuarded() const { return(m_lGrdCnt > 0); }
public:
class CGuard {
public:
CGuard(CResGuard& rg) : m_rg(rg) { m_rg.Guard(); };
~CGuard() { m_rg.Unguard(); }
protected:
CResGuard& m_rg;
};
private:
void Guard() { EnterCriticalSection(&m_cs); m_lGrdCnt++; }
void Unguard() { m_lGrdCnt--; LeaveCriticalSection(&m_cs); }

// Guard/Unguard can only be accessed by the nested CGuard class.
friend class CResGuard::CGuard;
private:
CRITICAL_SECTION m_cs;
long m_lGrdCnt; // # of EnterCriticalSection calls
};

------------------------------完整的代码------------------------------
5、完整的代码
以下是完整的代码,在C++Builder 6, Windows XP编译通过。
#pragma once
#include <Windows.h>
#include <memory> //线程安全使用的头文件
#ifndef SingletonH
#define SingletonH

using namespace std;

// Base SinglePattern Class
class SinglePattern
{
protected:
virtual void InitialInstance() = 0;
virtual void DisposeInstance() = 0;
};

// Thread Safe Class
class CResGuard
{
public:
CResGuard() { m_lGrdCnt = 0; InitializeCriticalSection(&m_cs); }
~CResGuard() { DeleteCriticalSection(&m_cs); }
// IsGuarded is used for debugging
BOOL IsGuarded() const { return(m_lGrdCnt > 0); }
public:
class CGuard {
public:
CGuard(CResGuard& rg) : m_rg(rg) { m_rg.Guard(); };
~CGuard() { m_rg.Unguard(); }
protected:
CResGuard& m_rg;
};
private:
void Guard() { EnterCriticalSection(&m_cs); m_lGrdCnt++; }
void Unguard() { m_lGrdCnt--; LeaveCriticalSection(&m_cs); }

// Guard/Unguard can only be accessed by the nested CGuard class.
friend class CResGuard::CGuard;
private:
CRITICAL_SECTION m_cs;
long m_lGrdCnt; // # of EnterCriticalSection calls
};

// Singleton Container
template <class T>
class Singleton
{
friend class auto_ptr<T>;
protected:
static auto_ptr<T> m_Instance;
static CResGuard _rs;
protected:
__fastcall Singleton(){};
virtual ~Singleton(){};
public:
static T* __fastcall GetInstance()
{
CResGuard::CGuard gd(_rs);
if(m_Instance.get() == NULL)
{
m_Instance.reset(new T());
}
return m_Instance.get();
}
};
template <class T>
CResGuard Singleton<T>::_rs;
template<class T>
auto_ptr<T> Singleton<T>::m_Instance;

// MACRO of Singleton Pattern to use
#define DECLARE_SINGLETON(type) \
friend class auto_ptr<type>; \
friend class Singleton<type>; \
public: \
static type *GetInstance() \
{ \
return Singleton<type>::GetInstance(); \
} \
protected: \
__fastcall type() \
{ \
InitialInstance(); \
} \
public: \
virtual ~type() \
{ \
DisposeInstance(); \
}
#endif

------------------------------如何使用------------------------------
6、如何使用
在你自己需要实现Singleton模式的类,使用宏定义,并实现两个纯虚函数,即可。
以下为一个使用示例:
class MySingle : public SinglePattern
{
DECLARE_SINGLETON(MySingle)
protected:
virtual void InitialInstance(){}
virtual void DisposeInstance(){}
public:
void Run(){};
};

int main(int argc, char* argv[])
{
MySingle::GetInstance()->Run();
return 0;
}

posted on 2006-11-29 14:08  SweetDream  阅读(526)  评论(0编辑  收藏  举报