使用l臨界區來實現單例模式

#include <stdlib.h>
#include <Windows.h>




class Mutex {  
public:  
Mutex()                      { InitializeCriticalSection(&section); }  
~Mutex()                     { DeleteCriticalSection(&section); }  
void  Enter()                { EnterCriticalSection(&section); }  
void  Leave()                { LeaveCriticalSection(&section); }  


struct Lock; 
Mutex(const Mutex&);  
Mutex& operator=(const Mutex&);  


protected:  




CRITICAL_SECTION section;  
};  


struct Mutex::Lock {  
Mutex& s;  
Lock(Mutex& s):s(s) { s.Enter(); }  
~Lock()               { s.Leave(); }  
};  


template<typename T, typename LOCK>
class HySingleton
{
public:
static T* Instance()
{
if (!m_pInstance)
{
MakeInstance();
}
return m_pInstance;
}


private:
/************************************************************************
Singleton這個類本身是一個永遠不會被實例化的類,所以沒有構造和析構調用
這裏確保“析構函數”被調用,其實現手法和編譯器處理析構函數很類似
確保程序退出的時候T的析構函數被調用,並且執行相關清理動作
************************************************************************/
static void MakeInstance()
{
//在這裏加入多線程保護,TODO
//這裏採用"雙檢測鎖定",在調用MakeInstance之前已經檢查過一次了
//LOCK::HyAutoLock _lock(m_lock);
Mutex::Lock _lock(m_lock);


if (!m_pInstance)
{
if(m_bDestroyed)
{
//Dead Reference Detected
OnDeadReference();


//OnDeadReference()沒有拋出異產的話
//對象就會"復活"
m_bDestroyed = false;
}


m_pInstance = new T;


//每次new完後,要確保delete
atexit(DestroySingleton);
}
}




/************************************************************************
如果在程序結束時,單體內的靜態成員已經析構。
有另一個壽命更長的對象訪問這個單體,就會出現引用失效。
因爲誰也不知道編譯按什麼順序銷燬對象(好像是先生成的後銷燬,即atexit以stack方式運作,見MSDN和C++方案)。
************************************************************************/


/************************************************************************
讓對象銷燬
************************************************************************/
static void DestroySingleton()
{
if(m_bDestroyed)
{
throw ("Singleton has been destroyed!");
}


//銷燬T的實例
delete m_pInstance;


//設置狀態
m_pInstance = NULL;


m_bDestroyed = true;
}


/************************************************************************
當檢測到調用已經銷燬的對象時,調用該函數
************************************************************************/
static void OnDeadReference()
{
//這裏什麼都不做可以讓已經被銷燬的靜態成員變量復活
//但是對於狀態複雜的對象,單實例化是不足以使對象工作的
//而且這裏好像沒有辦法插入T所需要的初始化代碼,因爲這個時候程序正在結束中
//所以也可以拋出異常結束程序
// throw std::runtime_error("Dead Reference Detected");


}


static T* m_pInstance;


static bool m_bDestroyed;


 
    static LOCK m_lock;


};
template<typename T, typename LOCK> T* HySingleton<T, LOCK>::m_pInstance = NULL;


template<typename T, typename LOCK> bool HySingleton<T, LOCK>::m_bDestroyed = false;


template<typename T, typename LOCK> LOCK HySingleton<T, LOCK>::m_lock;




#define USE_SINGLETON template<typename T,typename LOCK> friend class HySingleton;


class MyClass
//: public HySingleton<MyClass,Mutex>
{
 
public:
//friend class HySingleton<MyClass,Mutex>;
USE_SINGLETON
MyClass(){};
~MyClass(){};
void Print() { printf("testing %d\n",val); }
int val;
};   
 #define GetDeviceDefinePtr() HySingleton<MyClass,Mutex>::Instance()
 
int _tmain(int argc, _TCHAR* argv[])
{
 
HySingleton<MyClass,Mutex>::Instance()->val=9;
GetDeviceDefinePtr()->Print();

return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章