//////////////////////////////////////////////////////////////////////////////// /** * \file static_singleton.hpp * \date 6.8.2009 * \author Potěšil Josef xpotes03 * \brief Soubor obsahuje šablonu třídy cStaticSingleton. */ //////////////////////////////////////////////////////////////////////////////// #ifndef _STATIC_SINGLETON_HPP_ #define _STATIC_SINGLETON_HPP_ #include #include #include //////////////////////////////////////////////////////////////////////////////// /** * \brief Předdefinovaná třída podporující model větvení do vláken pro * spolupráci s šablonou cStaticSingleton pro použití ve vícevláknových * aplikacích. Využívá zámky z knihovny Boost::Threads. */ //////////////////////////////////////////////////////////////////////////////// struct MultiThreading { typedef boost::mutex mutex; typedef boost::mutex::scoped_lock scoped_lock; }; //////////////////////////////////////////////////////////////////////////////// /** * \brief Předdefinovaná třída pro spolupráci s šablonou cStaticSingleton pro * použití v jednovláknových aplikacích. */ //////////////////////////////////////////////////////////////////////////////// class SingleThreading { struct empty {}; struct scoped_guard { scoped_guard(empty& ) {} }; public: typedef empty mutex; typedef scoped_guard scoped_lock; }; //////////////////////////////////////////////////////////////////////////////// /** * \brief Šablonová třída obsahující jednoduchou implementaci návrhového vzoru * Singleton, která umožňuje vytvořit jedináčka z jakékoli třídy, která * má bezparametrový konstruktor. */ //////////////////////////////////////////////////////////////////////////////// template class cStaticSingleton { public: static Host* Instance(); static Host& GetInstance(); private: cStaticSingleton(); cStaticSingleton(const cStaticSingleton& s); cStaticSingleton& operator=(const cStaticSingleton& s); ~cStaticSingleton(); static Host& Create(); static Host& Access(); typedef Host& (*access_function)(); static Host* _instance; static bool _destroyed; static access_function _access; static typename ThreadingModel::mutex _mutex; }; //////////////////////////////////////////////////////////////////////////////// /** * \brief Funkce pro přístup k jediné instanci třídy. * \return Ukazatele na instanci. */ //////////////////////////////////////////////////////////////////////////////// template inline Host* cStaticSingleton::Instance() { return &(GetInstance()); } //////////////////////////////////////////////////////////////////////////////// /** * \brief Funkce pro přístup k jediné instanci třídy. * \return Referenci instanci. */ //////////////////////////////////////////////////////////////////////////////// template inline Host& cStaticSingleton::GetInstance() { return _access(); } //////////////////////////////////////////////////////////////////////////////// /** * \brief Konstruktor. */ //////////////////////////////////////////////////////////////////////////////// template cStaticSingleton::cStaticSingleton() { } //////////////////////////////////////////////////////////////////////////////// /** * \brief Destruktor. */ //////////////////////////////////////////////////////////////////////////////// template cStaticSingleton::~cStaticSingleton() { _instance = 0; _destroyed = true; _access = &cStaticSingleton::Create; } //////////////////////////////////////////////////////////////////////////////// /** * \brief Interní funkce třídy vytvářející samotnou instanci objektu. * Pro korektní práci ve vícevláknovém prostředí je potřeba * odkomentovat/upravit testující a uzamykací část */ //////////////////////////////////////////////////////////////////////////////// template Host& cStaticSingleton::Create() { typename ThreadingModel::scoped_lock scoped_lock(_mutex); if (!_instance) { if (!_destroyed) { // Vytvoř jedinou instanci a změň ukazatele _access, kterým byla // tato metoda zavolána, aby se již nezavolala a místo toho // se volala funkce zpřístupňující samotnou instanci static Host staticInstance; _instance = &staticInstance; _access = &cStaticSingleton::Access; } else { // Došlo k přístupu k již zničenému jedináčkovi throw std::runtime_error("Access to dead reference of an object."); } } return *_instance; } //////////////////////////////////////////////////////////////////////////////// /** * \brief Funkce zpřístupňující instanci hostující třídy. */ //////////////////////////////////////////////////////////////////////////////// template Host& cStaticSingleton::Access() { return *_instance; } //////////////////////////////////////////////////////////////////////////////// // Jedináčkova data //////////////////////////////////////////////////////////////////////////////// template Host* cStaticSingleton::_instance = 0; template bool cStaticSingleton::_destroyed = false; template typename cStaticSingleton::access_function cStaticSingleton::_access = &cStaticSingleton::Create; template typename ThreadingModel::mutex cStaticSingleton::_mutex; #endif // _STATIC_SINGLETON_HPP_