#ifndef __SINGLETON_HPP__ #define __SINGLETON_HPP__ #include #include #include namespace boost { /** Thanks to A. Alexandrescu for CTAssert concept. */ template class CTAssert; template<> class CTAssert{ }; /** See http://www.research.ibm.com/designpatterns/pubs/ph-jun96.txt about Singletons and Destroyers. This is destroyer for Singleton. Singleton must not be array. */ template class SingletonDestroyer : boost::noncopyable { /** SingletonDestroyer is only used with Singleton. The goal of SingletonDestroyer - to delete Singleton instance at program exit. */ template friend class Singleton; private: Doomed* doomed_; private: SingletonDestroyer() { typedef typename boost::is_array::type DoomedArrayType; CTAssert ____DOOMED_SINGLETON_MUST_NOT_BE_ARRAY____; /** Suppress unused variable warning */ ____DOOMED_SINGLETON_MUST_NOT_BE_ARRAY____; } ~SingletonDestroyer(){ delete doomed_; } private: void set_doomed(Doomed* doomed){ doomed_ = doomed; } }; template class Singleton : boost::noncopyable { private: static T* instance_; static SingletonDestroyer destroyer_; static boost::mutex mtx_instance_; public: static T& Instance() { /** Perform the Double-Check pattern. See http://www.research.ibm.com/designpatterns/pubs/ph-jun96.txt. */ if (instance_ == NULL) { boost::mutex::scoped_lock locker(mtx_instance_); if (instance_ == NULL) { instance_ = new T(); destroyer_.set_doomed(instance_); } } return *instance_; } }; template T* Singleton::instance_ = NULL; template SingletonDestroyer Singleton::destroyer_; template boost::mutex Singleton::mtx_instance_; } // !namespace boost #define SINGLETON_IS_MY_FRIEND \ template friend class Singleton; \ template friend class SingletonDestroyer; #endif // __SINGLETON_HPP__