首先,基于懒汉式写法,基于线程安全,因此,需要加锁,具体如下:
1.互斥锁写成类,实现自动加锁和解锁(criticalSection.h)
#ifndef __criticalSection_h__INCLUDED__ #define __criticalSection_h__INCLUDED__ #include <errno.h> // EBUSY...and the other errnos extern "C" { #include <pthread.h> // pthread_mutex_t } namespace cmn { class PThreadMutex { public: explicit PThreadMutex( pthread_mutex_t & mutex_r ): isAcquired_m( false ), mutex_rm ( mutex_r ) { beginCriticalSection(); }; virtual ~PThreadMutex() { endCriticalSection(); if ( isAcquired_m ) { // endCriticalSection() failed. This is a serious // error. return; } }; void beginCriticalSection() { int result = pthread_mutex_lock( &mutex_rm ); switch ( result ) { case 0: // success { isAcquired_m = true; return; } case EINVAL: // not initialized case EDEADLK: // already locked by this thread default: // should never happen { // TODO SOFTWARE1(result); isAcquired_m = false; return; }} }//beginCriticalSection void endCriticalSection() { if (!isAcquired_m) { return; } int result = pthread_mutex_unlock( &mutex_rm ); switch ( result ) { case 0: // success { isAcquired_m = false; return; } case EINVAL: // not initialized case EPERM: // not locked by this thread default: // should never happen { // TODO SOFTWARE1(result); return; } } }//endCriticalSection private: bool isAcquired_m; pthread_mutex_t & mutex_rm; }; //PThreadMutex };// namespace cmn #endif //__criticalSection_h__INCLUDED__
2. 懒汉式单例模式(singletonHolder.h)
#ifndef __singletonHolder_h__INCLUDED__ #define __singletonHolder_h__INCLUDED__ #include "criticalSection.h" // cmn::PThreadMutex namespace cmn { template < class T > class SingletonHolder { public: static T & getInstance(); // deleteInstance() shoule be used for debugging only. // Calling this will "empty" the singleton, however a subsequent call // to getInstance will recreate a brand new singleton. static void deleteInstance(); private: // prevent accidental construction SingletonHolder( ); SingletonHolder( const SingletonHolder & ); static T * volatile instance_spm; public: static pthread_mutex_t mutex_sm; }; template < class T > T & SingletonHolder<T>::getInstance() { // use the "double checked locking pattern" if ( !instance_spm ) { cmn::PThreadMutex lock(mutex_sm); if ( !instance_spm ) { instance_spm = new T; } } return *instance_spm; }//getInstance template < class T > void SingletonHolder<T>::deleteInstance() { // use the "double checked locking pattern" if ( instance_spm ) { cmn::PThreadMutex lock(mutex_sm); if ( instance_spm ) { delete instance_spm; instance_spm = 0; } } }//deleteInstance // We want to define a macro for use of this template. Mainly to simplify // the declaration of the static members... #define SINGLETON_HOLDER_INIT( name ) template class cmn::SingletonHolder<name>; template<> name* volatile cmn::SingletonHolder<name>::instance_spm = 0; template<> pthread_mutex_t cmn::SingletonHolder<name>::mutex_sm = PTHREAD_MUTEX_INITIALIZER; } // namespace cmn #endif //__singletonPerProcess_h__INCLUDED__
测试代码如下:
#include <iostream> #include "singletonHolder.h" #include "criticalSection.h" using namespace std; class Server; #define mdfServer_s ServerHandle::getInstance() typedef cmn::SingletonHolder<Server> ServerHandle; SINGLETON_HOLDER_INIT(Server) class Server { public: friend class cmn::SingletonHolder<Server>; void print(){cout<<i<<endl;} private: Server(); ~Server(); int i ; }; Server::Server():i(0){} Server::~Server(){} int main() { (void)mdfServer_s; mdfServer_s.print(); return 0; }
结果输出:0