//////////////////////////////////////////////////////////////////
//
// singleton.h
//
// All singleton objects are put into a list
// so that it would be delete when program exits.
//
//
// This work is published under the GNU Public License (GPL)
// see file COPYING for details.
// We also explicitely grant the right to link this code
// with the OpenH323 library.
//
// History:
// 2001/07/11 initial version (Chih-Wei Huang)
//
//////////////////////////////////////////////////////////////////
#ifndef SINGLETON_H
#define SINGLETON_H "@(#) $Id: singleton.h,v 1.13 2006/04/14 13:56:19 willamowius Exp $"
// STL
#include <list>
#include <algorithm>
#include <stdexcept>
//
// a list of pointers that would delete all objects
// referred by the pointers in the list on destruction
//
template<class T> class listptr : public std::list<void *> {
public:
listptr() : clear_list(false) {}
~listptr();
bool clear_list;
private:
static void delete_obj(void *t) { delete static_cast<T *>(t); }
};
template<class T> listptr<T>::~listptr()
{
clear_list=true;
std::for_each(begin(), end(), delete_obj);
}
// Base class for all singletons
class SingletonBase {
public:
SingletonBase(const char *);
virtual ~SingletonBase();
private:
const char *m_name;
// Note the SingletonBase instance is not singleton itself :p
// However, list of singletons *are* singleton
// But we can't put the singleton into the list :(
static listptr<SingletonBase> _instance_list;
};
//
// A singleton class should be derived from this template.
// class Ts : public Singleton<Ts> {
// ...
// };
//
// If the class is instantiated more than once,
// a runtime error would be thrown
//
// I provide two ways to access the singleton:
// (since I'm not sure which is better)
// T::Instance() or InstanceOf<T>
//
template<class T> class Singleton : public SingletonBase {
public:
static T *Instance();
template<class U> static T *Instance(const U &);
protected:
Singleton(const char *);
~Singleton();
public:
static T *m_Instance;
static PMutex m_CreationLock;
};
template<class T> Singleton<T>::Singleton(const char *n) : SingletonBase(n)
{
// if (m_Instance != 0)
// throw std::runtime_error("Duplicate instances");
}
template<class T> Singleton<T>::~Singleton()
{
PWaitAndSignal lock(m_CreationLock);
m_Instance = 0;
}
// Function to access the singleton
template<class T> T *Singleton<T>::Instance()
{
if (m_Instance == 0) {
PWaitAndSignal lock(m_CreationLock);
// We have to check it again after we got the lock
if (m_Instance == 0)
m_Instance = new T;
}
return m_Instance;
}
#ifndef _WIN32 // VC++ doesn't support nested template?
template<class T> template <class U> T *Singleton<T>::Instance(const U &u)
{
if (m_Instance == 0) {
PWaitAndSignal lock(m_CreationLock);
// We have to check it again after we got the lock
if (m_Instance == 0)
m_Instance = new T(u);
}
return m_Instance;
}
#endif
// Function to access the singleton
template<class T> T *InstanceOf()
{
if (Singleton<T>::m_Instance == 0) {
PWaitAndSignal lock(Singleton<T>::m_CreationLock);
// We have to check it again after we got the lock
if (Singleton<T>::m_Instance == 0)
Singleton<T>::m_Instance = new T;
}
return Singleton<T>::m_Instance;
}
// static members
template<class T> T *Singleton<T>::m_Instance=0;
template<class T> PMutex Singleton<T>::m_CreationLock;
#endif // SINGLETON_H
syntax highlighted by Code2HTML, v. 0.9.1