分享一个线程安全的单例模板类

单例模式应该说是最简单的设计模式了。在此分享一个线程安全的单例模板类。

template <typename Type>

class CSingleton

{

public:

static Type* GetInstance()

{

// kBeingCreatedMarker用来表示单例实例正在创建过程中。

// 此处初始化为1是因为操作系统不会分配地址为1的指针。

static const volatile intptr_t kBeingCreatedMarker = 1;

// 如果m_pInstance不为空且不是正在创建,则返回m_pInstance

if (m_pInstance != NULL && m_pInstance != kBeingCreatedMarker)  {

return reinterpret_cast<Type*>(m_pInstance);

}

// 使用InterlockedCompareExchange函数保证原子操作

// 函数判断m_pInstance是否等于NULL,如果是则将m_pInstance赋值为kBeingCreatedMarker

// 函数返回值为m_pInstance的初始值,通过判断返回值是否等于NULL得知是否可以进行实例化

if (InterlockedCompareExchange(

reinterpret_cast<volatile LONG*>(&m_pInstance),

static_cast<LONG>(kBeingCreatedMarker),

static_cast<LONG>(NULL)) == NULL)  {

static Type newval;

m_pInstance = reinterpret_cast<intptr_t>(&newval);

return &newval;

}

// 如果m_pInstance是kBeingCreatedMarker,即表示正在创建中

// SwitchToThread让出剩余的时间片等待创建过程完成

while (m_pInstance == kBeingCreatedMarker)

{

SwitchToThread();

}

// 到达此处表明创建过程已经完成了

return reinterpret_cast<Type*>(m_pInstance);

}

Type& operator*()

{

return *GetInstance();

}

Type* operator->()

{

return GetInstance();

}

private:

static volatile intptr_t m_pInstance;

};

template <typename Type>

volatile intptr_t CSingleton<Type>::m_pInstance = NULL;

假设我们有个CCmdManager类

class CCmdManager

{

public:

CCmdManager()

{

std::cout << "Hello, I am the only one!";

};

};

使用方法很简单,如下:

int main()

{

CCmdManager *pMgr = CSingleton<CCmdManager>::GetInstance();

CCmdManager &mgr = *(CSingleton<CCmdManager>::GetInstance());

}

如果我们想要完全限制CCmdManager不被实例化第二次,我们可以这么做

class CCmdManager

{

private:

CCmdManager()

{

std::cout << "Hello, I am the only one!";

};

friend class CSingleton<CCmdManager>;

};

通过将构造函数设置为private,且仅对class CSingleton<CCmdManager>开放,就可以保证用户只能使用CCmdManager *pMgr = CSingleton<CCmdManager>::GetInstance()这种方式调用了。

顺便说一下,这个代码的一些局限性

1. 因为使用了InterlockedCompareExchange这个函数,所以只能在Windows下使用,但是不可否定的是这个函数的效率极高,完成比较并交换只要一条指令。

wps2B92.tmp

2. CSingleton在实例化对象时,只支持默认构造函数。一般情况下,这个也是可以接受的。

posted on 2015-05-24 12:26  sudosky  阅读(412)  评论(0编辑  收藏  举报