模板singleton模式的C++实现
近期回过头整理了一下singleton模式,看了别人写的关于singleton的介绍。发现这个singleton模式虽然简单,但要写一个稳定/线程安全/泛型的模板singleton,还是需要一点技巧的。经过整理,要写一个模板的singlton至少需要以下几个知识点:
1:singleton
2:static类成员实例延迟创建。
3:static类实例创建互斥实现,即线程安全。
4:double check技巧。 【Ref:http://www.ibm.com/developerworks/library/j-dcl/index.html】
5:模板。
6:static成员变量初始化。
7:singleton关闭类实例
下面上singleton实现代码,测试可用。
1 #pragma once 2 /************************************************************************ 3 singleton模式类模板 4 1:延迟创建类实例 2:double check 3:互斥访问 4:模板 5 ************************************************************************/ 6 #ifndef WHG_SINGLETON 7 #define WHG_SINGLETON 8 9 #include "ThreadLockCs.h" 10 11 template<class T> 12 class CSingleton 13 { 14 private: 15 static T* _instance; 16 CSingleton(void); 17 static CThreadLockCs lcs; 18 public: 19 static T* Instance(void); 20 static void Close(void); 21 }; 22 23 //模板类static变量 24 template<class T> 25 T* CSingleton<T>::_instance = NULL; 26 27 template<class T> 28 CThreadLockCs CSingleton<T>::lcs; 29 30 //模板类方法实现 31 template<class T> 32 CSingleton<T>::CSingleton(void) 33 { 34 } 35 36 template<class T> 37 T* CSingleton<T>::Instance(void) 38 { 39 //double-check 40 //延迟创建,只有调用方访问Instance才会创建类实例 41 if (_instance == NULL) 42 { 43 //互斥访问锁,用CriticalSection实现 44 lcs.lock(); 45 if (_instance == NULL) 46 { 47 _instance = new T; 48 } 49 lcs.unlock(); 50 } 51 return _instance; 52 } 53 54 template<class T> 55 void CSingleton<T>::Close(void) 56 { 57 if (_instance) 58 { 59 delete _instance; 60 } 61 } 62 63 #endif
CSingleton内用到的CThreadLockCs 实现如下:
1 //互斥访问锁 2 #ifndef WHG_THREAD_LOCKCS 3 #define WHG_THREAD_LOCKCS 4 5 //#include <Windows.h> 6 7 class CThreadLockCs 8 { 9 public: 10 CThreadLockCs(){InitializeCriticalSection(&m_cs);} 11 ~CThreadLockCs(){DeleteCriticalSection(&m_cs);} 12 void lock(){EnterCriticalSection(&m_cs);} 13 void unlock(){LeaveCriticalSection(&m_cs);} 14 private: 15 CRITICAL_SECTION m_cs; 16 }; 17 #endif
调用方法很简单:
1:用typedef申明一个变量名
1 typedef CSingleton<CListen> LISTEN;
2:调用的地方写
1 LISTEN::Instance()->SetAddress(8828,"127.0.0.1");
3:关闭的地方写
1 LISTEN::Close();