2007-09-06 22:13:26 +02:00
|
|
|
/*
|
|
|
|
|
SINGLETON.hpp - template for implementing the singleton pattern
|
|
|
|
|
|
|
|
|
|
Copyright (C) CinelerraCV
|
|
|
|
|
2007, Christian Thaeter <ct@pipapo.org>
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
|
|
|
|
published by the Free Software Foundation; either version 2 of the
|
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
|
|
|
|
====================================================================
|
|
|
|
|
This code is heavily inspired by
|
|
|
|
|
The Loki Library (loki-lib/trunk/include/loki/Singleton.h)
|
|
|
|
|
Copyright (c) 2001 by Andrei Alexandrescu
|
|
|
|
|
This Loki code accompanies the book:
|
|
|
|
|
Alexandrescu, Andrei. "Modern C++ Design: Generic Programming
|
|
|
|
|
and Design Patterns Applied".
|
|
|
|
|
Copyright (c) 2001. Addison-Wesley. ISBN 0201704315
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef CINELERRA_SINGLETON_H
|
|
|
|
|
#define CINELERRA_SINGLETON_H
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "common/singletonpolicies.hpp" ///< several Policies usable together with singleton
|
|
|
|
|
|
2007-09-10 06:45:36 +02:00
|
|
|
#include "common/util.hpp"
|
|
|
|
|
#include "nobugcfg.h"
|
|
|
|
|
|
|
|
|
|
#include <boost/bind.hpp>
|
2007-09-06 22:13:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace cinelerra
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/**
|
2007-09-10 06:45:36 +02:00
|
|
|
* A configurable Template for implementing Singletons.
|
|
|
|
|
* Actually this is a Functor object, which could be placed into a static field
|
|
|
|
|
* of the Singleton (target) class or used directly.
|
|
|
|
|
* @note internally uses static fields, so all functor instances share pInstance_
|
2007-09-06 22:13:26 +02:00
|
|
|
*/
|
|
|
|
|
template
|
2007-09-10 06:45:36 +02:00
|
|
|
< class SI, // the class to make Singleton
|
2007-09-06 22:13:26 +02:00
|
|
|
template <class> class Create = singleton::Static, // how to create/destroy the instance
|
|
|
|
|
template <class> class Life = singleton::Automatic, // how to manage Singleton Lifecycle
|
|
|
|
|
template <class> class Threading = singleton::IgnoreThreadsafety //TODO use Multithreaded!!!
|
|
|
|
|
>
|
|
|
|
|
class Singleton
|
|
|
|
|
{
|
2007-09-10 06:45:36 +02:00
|
|
|
typedef typename Threading<SI>::VolatileType SType;
|
|
|
|
|
typedef typename Threading<SI>::Lock ThreadLock;
|
2007-09-06 22:13:26 +02:00
|
|
|
static SType* pInstance_;
|
|
|
|
|
static bool isDead_;
|
|
|
|
|
|
2007-09-10 06:45:36 +02:00
|
|
|
public:
|
|
|
|
|
/** Interface to be used by Singleton's clients.
|
|
|
|
|
* Manages internally the instance creation, lifecycle
|
|
|
|
|
* and access handling in a multithreaded context.
|
|
|
|
|
* @return "the" single instance of class S
|
|
|
|
|
*/
|
|
|
|
|
SI& operator() ()
|
|
|
|
|
{
|
|
|
|
|
if (!pInstance_)
|
|
|
|
|
{
|
2007-09-14 19:18:11 +02:00
|
|
|
ThreadLock guard SIDEEFFECT;
|
2007-09-10 06:45:36 +02:00
|
|
|
if (!pInstance_)
|
|
|
|
|
{
|
|
|
|
|
if (isDead_)
|
|
|
|
|
{
|
|
|
|
|
Life<SI>::onDeadReference();
|
|
|
|
|
isDead_ = false;
|
|
|
|
|
}
|
|
|
|
|
pInstance_ = Create<SI>::create();
|
|
|
|
|
Life<SI>::scheduleDelete (&destroy);
|
|
|
|
|
} }
|
|
|
|
|
ENSURE (pInstance_);
|
|
|
|
|
ENSURE (!isDead_);
|
|
|
|
|
return *pInstance_;
|
|
|
|
|
}
|
2007-09-06 22:13:26 +02:00
|
|
|
|
|
|
|
|
private:
|
2007-09-10 06:45:36 +02:00
|
|
|
/** @internal helper used to delegate destroying the single instance
|
|
|
|
|
* to the Create policy, at the same time allowing the Life policy
|
|
|
|
|
* to control the point in the Application lifecycle when the
|
|
|
|
|
* destruction of this instance occures.
|
|
|
|
|
*/
|
|
|
|
|
static void destroy()
|
|
|
|
|
{
|
|
|
|
|
REQUIRE (!isDead_);
|
|
|
|
|
Create<SI>::destroy (pInstance_);
|
|
|
|
|
pInstance_ = 0;
|
|
|
|
|
isDead_ = true;
|
|
|
|
|
}
|
2007-09-06 22:13:26 +02:00
|
|
|
};
|
2007-09-10 06:45:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
// Storage for Singleton's static fields...
|
|
|
|
|
template
|
|
|
|
|
< class SI,
|
|
|
|
|
template <class> class C,
|
|
|
|
|
template <class> class L,
|
|
|
|
|
template <class> class T
|
|
|
|
|
>
|
|
|
|
|
typename Singleton<SI,C,L,T>::SType*
|
|
|
|
|
Singleton<SI,C,L,T>::pInstance_;
|
2007-09-06 22:13:26 +02:00
|
|
|
|
2007-09-10 06:45:36 +02:00
|
|
|
template
|
|
|
|
|
< class SI,
|
|
|
|
|
template <class> class C,
|
|
|
|
|
template <class> class L,
|
|
|
|
|
template <class> class T
|
|
|
|
|
>
|
|
|
|
|
bool Singleton<SI,C,L,T>::isDead_;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///// TODO: get rid of the static fields?
|
|
|
|
|
///// is tricky because of invoking the destructors. If we rely on instance vars,
|
|
|
|
|
///// the object may already have been released when the runtime system calls the
|
|
|
|
|
///// destructors of static objects at shutdown.
|
|
|
|
|
|
|
|
|
|
/** @internal used to link together the Create policy and Life policy.
|
|
|
|
|
* @return a functor object for invoking this->destroy() */
|
|
|
|
|
/* singleton::DelFunc getDeleter()
|
|
|
|
|
{
|
|
|
|
|
return boost::bind (&Singleton<SI,Create,Life,Threading>::destroy,
|
|
|
|
|
this);
|
|
|
|
|
}
|
|
|
|
|
*/
|
2007-09-06 22:13:26 +02:00
|
|
|
|
2007-09-10 06:45:36 +02:00
|
|
|
/* template<class T>
|
|
|
|
|
class DelFunc
|
|
|
|
|
{
|
|
|
|
|
typedef void (T::*Fp)(void);
|
|
|
|
|
T* t_;
|
|
|
|
|
Fp fun_;
|
|
|
|
|
public:
|
|
|
|
|
DelFunc (T* t, Fp f) : t_(t), fun_(f) {}
|
|
|
|
|
void operator() () { (t_->*fun_)(); }
|
|
|
|
|
};
|
|
|
|
|
*/
|
2007-09-06 22:13:26 +02:00
|
|
|
} // namespace cinelerra
|
|
|
|
|
#endif
|