共享一個Singleton template的實現:
Singleton.hpp如下
************************************************************************ * Template of Singleton, threads safe. * by xiuleili 2013-7-5 ************************************************************************/ #pragma once #include <memory> #ifdef WIN32 #include "ResGuard.hpp" #else #include "ResGuard_linux.hpp" #endif template <class T> class Singleton { public: // return instance of the singleton static inline T* instance(){ if( 0 == _instance.get() ) { ResGuard::Lock gd(_rs); if( 0== _instance.get()) { _instance.reset ( new T); } } return _instance.get(); } private: Singleton(void){} ~Singleton(void){} Singleton(const Singleton&){} Singleton & operator= (const Singleton &){} static std::auto_ptr<T> _instance; // auto_ptr used for release the resource. static ResGuard _rs; // }; template <class T> std::auto_ptr<T> Singleton<T>::_instance; template <class T> ResGuard Singleton<T>::_rs; // use this macro to declare a singleton #define DECLARE_SINGLETON_CLASS( type ) \ friend class std::auto_ptr< type >;\ friend class Singleton< type >; // How to use: // class A{ // private: // A(){} // A(const A &){} // ~A(){} // A & operator=(const A &){} // DECLARE_SINGLETON_CLASS(A); // }; // // declare the singleton: // typedef Singleton<A> theA; // // call it somewhere like this: // theA::instance()->foo(); /************************************************************************ * Template of Singleton, threads safe. * by xiuleili 2013-7-5 ************************************************************************/ #pragma once #include <memory> #ifdef WIN32 #include "ResGuard.hpp" #else #include "ResGuard_linux.hpp" #endif template <class T> class Singleton { public: // return instance of the singleton static inline T* instance(){ if( 0 == _instance.get() ) { ResGuard::Lock gd(_rs); if( 0== _instance.get()) { _instance.reset ( new T); } } return _instance.get(); } private: Singleton(void){} ~Singleton(void){} Singleton(const Singleton&){} Singleton & operator= (const Singleton &){} static std::auto_ptr<T> _instance; // auto_ptr used for release the resource. static ResGuard _rs; // }; template <class T> std::auto_ptr<T> Singleton<T>::_instance; template <class T> ResGuard Singleton<T>::_rs; // use this macro to declare a singleton #define DECLARE_SINGLETON_CLASS( type ) \ friend class std::auto_ptr< type >;\ friend class Singleton< type >; // How to use: // class A{ // private: // A(){} // A(const A &){} // ~A(){} // A & operator=(const A &){} // DECLARE_SINGLETON_CLASS(A); // }; // // declare the singleton: // typedef Singleton<A> theA; // // call it somewhere like this: // theA::instance()->foo(); Resguard.hpp
* Implementation of ResGuard on Windows. * see <<windows kernal var cpp>> * by xiuleili 2013-7-5 */ #pragma once #ifndef _UNIX #include <windows.h> /////////////////////////////////////////////////////////////////////////////// // Instances of this class will be accessed by multiple threads. So, // all members of this class (except the constructor and destructor) // must be thread-safe. class ResGuard { public: ResGuard() { m_guardcount = 0; InitializeCriticalSection(&m_cs); } ~ResGuard() { DeleteCriticalSection(&m_cs); } // IsGuarded is used for debugging bool isgurded() const { return(m_guardcount > 0); } public: class Lock { public: Lock(ResGuard& rg) : m_rg(rg) { m_rg.Guard(); }; ~Lock() { m_rg.Unguard(); } private: ResGuard& m_rg; }; private: void Guard() { EnterCriticalSection(&m_cs); m_guardcount++; } void Unguard() { m_guardcount--; LeaveCriticalSection(&m_cs); } // Guard/Unguard can only be accessed by the nested CGuard class. friend class ResGuard::Lock; private: CRITICAL_SECTION m_cs; long m_guardcount; // # of EnterCriticalSection calls }; #endif /* * Implementation of ResGuard on Windows. * see <<windows kernal var cpp>> * by xiuleili 2013-7-5 */ #pragma once #ifndef _UNIX #include <windows.h> /////////////////////////////////////////////////////////////////////////////// // Instances of this class will be accessed by multiple threads. So, // all members of this class (except the constructor and destructor) // must be thread-safe. class ResGuard { public: ResGuard() { m_guardcount = 0; InitializeCriticalSection(&m_cs); } ~ResGuard() { DeleteCriticalSection(&m_cs); } // IsGuarded is used for debugging bool isgurded() const { return(m_guardcount > 0); } public: class Lock { public: Lock(ResGuard& rg) : m_rg(rg) { m_rg.Guard(); }; ~Lock() { m_rg.Unguard(); } private: ResGuard& m_rg; }; private: void Guard() { EnterCriticalSection(&m_cs); m_guardcount++; } void Unguard() { m_guardcount--; LeaveCriticalSection(&m_cs); } // Guard/Unguard can only be accessed by the nested CGuard class. friend class ResGuard::Lock; private: CRITICAL_SECTION m_cs; long m_guardcount; // # of EnterCriticalSection calls }; #endif Resguard_linux.hpp
* implementation of ResGuard. * See <POSIX Muti-threads programming> * by xiuleili 2013-7-5 */ #pragma once #include <pthread.h> // Instances of this class will be accessed by multiple threads. So, // all members of this class (except the constructor and destructor) // must be thread-safe. class ResGuard { public: ResGuard() { m_guardcount = 0; pthread_mutex_init(&m_cs, NULL); } ~ResGuard() { pthread_mutex_destroy(&m_cs); } // IsGuarded is used for debugging bool isgurded() const { return(m_guardcount > 0); } public: class Lock { public: Lock(ResGuard& rg) : m_rg(rg) { m_rg.Guard(); }; ~Lock() { m_rg.Unguard(); } private: ResGuard& m_rg; }; private: void Guard() { pthread_mutex_lock(&m_cs); m_guardcount++; } void Unguard() { m_guardcount--; pthread_mutex_unlock(&m_cs); } // Guard/Unguard can only be accessed by the nested Guard class. friend class ResGuard::Lock; private: pthread_mutex_t m_cs; long m_guardcount; // # of EnterCriticalSection calls }; /* * implementation of ResGuard. * See <POSIX Muti-threads programming> * by xiuleili 2013-7-5 */ #pragma once #include <pthread.h> // Instances of this class will be accessed by multiple threads. So, // all members of this class (except the constructor and destructor) // must be thread-safe. class ResGuard { public: ResGuard() { m_guardcount = 0; pthread_mutex_init(&m_cs, NULL); } ~ResGuard() { pthread_mutex_destroy(&m_cs); } // IsGuarded is used for debugging bool isgurded() const { return(m_guardcount > 0); } public: class Lock { public: Lock(ResGuard& rg) : m_rg(rg) { m_rg.Guard(); }; ~Lock() { m_rg.Unguard(); } private: ResGuard& m_rg; }; private: void Guard() { pthread_mutex_lock(&m_cs); m_guardcount++; } void Unguard() { m_guardcount--; pthread_mutex_unlock(&m_cs); } // Guard/Unguard can only be accessed by the nested Guard class. friend class ResGuard::Lock; private: pthread_mutex_t m_cs; long m_guardcount; // # of EnterCriticalSection calls };