C++ Singleton设计模式,网上讨论文章也比较多,一般推荐较多的是boost的实现,简单且线程安全。
但个人更推荐Google chrome浏览器带的Singleton实现,通过附加一个AtExit类,支持多类型singleton实例以后进先出次序可控析构。
如下面示例代码,当at_exit对象析构时,所有Singleton实例也会被自动删除。
void main()
{ AtExit at_exit; SingletonClass1::get()->foo(); SingletonClass2::get()->bar(); }
由于Google的Singleton代码实现比较复杂,我简化实现了一个,代码如下:
#pragma once #include <functional> #include <stack> #include <memory> #include <assert.h> #if !defined(_MSC_VER) || _MSC_VER >= 1700 #include <mutex> #endif class AtExit { public: typedef std::function<void ()> ExitCallback; AtExit() { assert(!*instance()); if(!*instance()) *instance() = this; } ~AtExit() { *instance() = nullptr; while(!callbacks_.empty()) { (callbacks_.top())(); callbacks_.pop(); } } static void Add(ExitCallback exit_callback) { assert(*instance()); if(*instance()) (*instance())->callbacks_.push(exit_callback); } private: std::stack<ExitCallback> callbacks_; static AtExit** instance() { static AtExit* the_instance = nullptr; return &the_instance; } }; template <typename Type, bool release_at_exit = true> class Singleton { public: friend class std::unique_ptr<Type>; static Type* get() { if (instance_.get() == NULL) { std::lock_guard<std::mutex> lock(singleton_mutex_); if (instance_.get() == NULL) { instance_.reset(new Type()); if(release_at_exit) AtExit::Add(Singleton<Type,release_at_exit>::release); } } return instance_.get(); } static void release() { std::lock_guard<std::mutex> lock(singleton_mutex_); if(instance_.get()) instance_.reset(); } static bool is_null() { return instance_.get() == nullptr; } protected: typedef class Singleton<Type> BaseSingletonType; typedef std::default_delete<Type> DefaultDeleteType; Singleton() {} ~Singleton() {} private: static std::mutex singleton_mutex_; static std::unique_ptr<Type> instance_; Singleton( const Singleton& ); const Singleton& operator=( const Singleton& ); }; template <typename Type, bool release_at_exit> std::unique_ptr<Type> Singleton<Type,release_at_exit>::instance_; template <typename Type, bool release_at_exit> std::mutex Singleton<Type,release_at_exit>::singleton_mutex_; #define SINGLETON_FRIENDS \ friend BaseSingletonType; \ friend DefaultDeleteType;
由于同步锁用了c++11的std::mutex, 对于VS2010及以前的编译器,可以在include前加上下面的简化版本std::mutex实现, 如是低版本gcc可以自己实现一个:
#pragma once #if defined(_WIN32) && _MSC_VER < 1700 namespace std{ class mutex : public CRITICAL_SECTION { public: mutex(mutex const&); mutex& operator=(mutex const&); mutex() { ::InitializeCriticalSectionAndSpinCount( this, 0 ); } ~mutex() { ::DeleteCriticalSection( this ); } void lock() { ::EnterCriticalSection( this ); } void unlock() { ::LeaveCriticalSection( this ); } bool try_lock() { return ( ::TryEnterCriticalSection( this ) ) != 0; } }; template <class Mutex> class lock_guard { public: typedef Mutex mutex_type; explicit lock_guard(mutex_type& m) : m_(m) { m_.lock(); } ~lock_guard() { m_.unlock(); } lock_guard(lock_guard const& ); lock_guard& operator=(lock_guard const& ); private: mutex_type& m_; }; } #endif
调用示例:
class Test : public Singleton<Test> { public: void foo() { } private: Test(){} ~Test(){} SINGLETON_FRIENDS }; void main() { AtExit at_exit; Test::get()->foo(); }