在服務器開發中,大量的使用了singleton模式, 以我的工作為例, 用于打印log的類是一個singleton, 內存池管理器是一個singleton...雖然singleton模式實現起來不難, 但是為了避免重復開發, 我還是決定應該把這個類的實現單獨拿出來,同時, singleton類還需要支持多線程,但是我從來不寫多線程的服務器程序, 對多線程的支持可以通過預編譯宏來實現.我把操作多線程鎖, 以及singleton類都放在這篇文章中, 多線程鎖僅支持linux.
threadmutex.h
/********************************************************************
created: 2008/08/01
filename: threadmutex.h
author: Lichuang
purpose: 線程鎖類, 由是否定義宏__USE_THREAD__來決定是否使用該類
*********************************************************************/
#ifndef __THREAD_MUTEX_H__
#define __THREAD_MUTEX_H__
#ifdef __USE_THREAD__
#include <pthread.h>
#define THREAD_LOCK(tThreadMutex) tThreadMutex.Lock()
#define THREAD_UNLOCK(tThreadMutex) tThreadMutex.UnLock()
#else
#define THREAD_LOCK(tThreadMutex)
#define THREAD_UNLOCK(tThreadMutex)
#endif
class CThreadMutex
{
public:
CThreadMutex();
~CThreadMutex();
int Lock();
int UnLock();
private:
#ifdef __USE_THREAD__
pthread_mutex_t m_tThreadMutex;
#endif
};
#endif /* __THREAD_MUTEX_H__ */
threadmutex.cpp
/********************************************************************
created: 2008/08/01
filename: threadmutex.h
author: Lichuang
purpose: 線程鎖類, 由是否定義宏__USE_THREAD__來決定是否使用該
線程鎖類
*********************************************************************/
#include "threadmutex.h"
#ifdef __USE_THREAD__
CThreadMutex::CThreadMutex()
{
::pthread_mutex_init(&m_tThreadMutex, NULL);
}
CThreadMutex::~CThreadMutex()
{
::pthread_mutex_destroy(&m_tThreadMutex);
}
int CThreadMutex::Lock()
{
return ::pthread_mutex_lock(&m_tThreadMutex);
}
int CThreadMutex::UnLock()
{
return ::pthread_mutex_unlock(&m_tThreadMutex);
}
#else
CThreadMutex::CThreadMutex()
{
}
CThreadMutex::~CThreadMutex()
{
}
int CThreadMutex::Lock()
{
return 0;
}
int CThreadMutex::UnLock()
{
return 0;
}
#endif
singleton.h
/********************************************************************
created: 2008/08/01
filename: singleton.h
author: Lichuang
purpose: 實現單件模式的虛擬基類, 其它需要實現為singleton的類可以
繼承自這個類
支持多線程, 采用智能指針實現自動回收內存
*********************************************************************/
#ifndef __SINGLETON_H__
#define __SINGLETON_H__
#include <memory>
#include "threadmutex.h"
using namespace std;
#define DECLARE_SINGLETON_CLASS( type ) \
friend class auto_ptr< type >; \
friend class CSingleton< type >;
template <class T>
class CSingleton
{
public:
static T* GetInstance();
protected:
CSingleton()
{
}
virtual ~CSingleton()
{
}
protected:
friend class auto_ptr<CSingleton>;
static auto_ptr<T> m_pInstance;
static CThreadMutex m_tThreadMutex;
};
template <class T>
auto_ptr<T> CSingleton<T>::m_pInstance;
template <class T>
CThreadMutex CSingleton<T>::m_tThreadMutex;
template <class T>
inline T* CSingleton<T>::GetInstance()
{
if (0 == m_pInstance.get())
{
THREAD_LOCK(m_tThreadMutex);
if (0 == m_pInstance.get())
{
m_pInstance.reset(::new T);
}
THREAD_UNLOCK(m_tThreadMutex);
}
return m_pInstance.get();
}
#endif /* __SINGLETON_H__ */
使用示例:
#include <iostream>
#include "singleton.h"
using namespace std;
class CTestSingleton
: public CSingleton<CTestSingleton>
{
public:
void Set(int a)
{
m_a = a;
}
int Get()
{
return m_a;
}
private:
CTestSingleton()
: m_a(0)
{
}
DECLARE_SINGLETON_CLASS(CTestSingleton)
private:
int m_a;
};
int main()
{
if (NULL == CTestSingleton::GetInstance())
{
cout << "GetInstance() error!" << endl;
}
cout << "before set: " << CTestSingleton::GetInstance()->Get() << endl;
CTestSingleton::GetInstance()->Set(100);
cout << "after set: " << CTestSingleton::GetInstance()->Get() << endl;
return 0;
}