模板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();