使用l臨界區來實現單例模式
#include <stdlib.h>
#include <Windows.h>
class Mutex {
public:
Mutex() { InitializeCriticalSection(§ion); }
~Mutex() { DeleteCriticalSection(§ion); }
void Enter() { EnterCriticalSection(§ion); }
void Leave() { LeaveCriticalSection(§ion); }
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;
}
#include <Windows.h>
class Mutex {
public:
Mutex() { InitializeCriticalSection(§ion); }
~Mutex() { DeleteCriticalSection(§ion); }
void Enter() { EnterCriticalSection(§ion); }
void Leave() { LeaveCriticalSection(§ion); }
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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.