You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
6.2 KiB

////////////////////////////////////////////////////////////////////////////////
/**
* \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 <stdexcept>
#include <boost/noncopyable.hpp>
#include <boost/thread/mutex.hpp>
////////////////////////////////////////////////////////////////////////////////
/**
* \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 Host, class ThreadingModel = SingleThreading>
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<class Host, class ThreadingModel>
inline Host* cStaticSingleton<Host, ThreadingModel>::Instance()
{
return &(GetInstance());
}
////////////////////////////////////////////////////////////////////////////////
/**
* \brief Funkce pro přístup k jediné instanci třídy.
* \return Referenci instanci.
*/
////////////////////////////////////////////////////////////////////////////////
template<class Host, class ThreadingModel>
inline Host& cStaticSingleton<Host, ThreadingModel>::GetInstance()
{
return _access();
}
////////////////////////////////////////////////////////////////////////////////
/**
* \brief Konstruktor.
*/
////////////////////////////////////////////////////////////////////////////////
template<class Host, class ThreadingModel>
cStaticSingleton<Host, ThreadingModel>::cStaticSingleton()
{
}
////////////////////////////////////////////////////////////////////////////////
/**
* \brief Destruktor.
*/
////////////////////////////////////////////////////////////////////////////////
template<class Host, class ThreadingModel>
cStaticSingleton<Host, ThreadingModel>::~cStaticSingleton()
{
_instance = 0;
_destroyed = true;
_access = &cStaticSingleton<Host, ThreadingModel>::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<class Host, class ThreadingModel>
Host& cStaticSingleton<Host, ThreadingModel>::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<Host, ThreadingModel>::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<class Host, class ThreadingModel>
Host& cStaticSingleton<Host, ThreadingModel>::Access()
{
return *_instance;
}
////////////////////////////////////////////////////////////////////////////////
// Jedináčkova data
////////////////////////////////////////////////////////////////////////////////
template<class Host, class TM>
Host* cStaticSingleton<Host, TM>::_instance = 0;
template<class H, class TM>
bool cStaticSingleton<H, TM>::_destroyed = false;
template<class H, class TM> typename cStaticSingleton<H, TM>::access_function
cStaticSingleton<H, TM>::_access = &cStaticSingleton<H, TM>::Create;
template<class H, class ThreadingModel> typename ThreadingModel::mutex
cStaticSingleton<H, ThreadingModel>::_mutex;
#endif // _STATIC_SINGLETON_HPP_