码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-05-24 12:57:17      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:

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

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下使用,但是不可否定的是这个函数的效率极高,完成比较并交换只要一条指令。

技术分享

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

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

标签:

原文地址:http://www.cnblogs.com/SudoSky/p/4525648.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!