/* SINGLETONFACTORY.hpp - template for implementing the singleton pattern Copyright (C) Lumiera.org 2008, Hermann Vosseler 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 LUMIERA_SINGLETONFACTORY_H #define LUMIERA_SINGLETONFACTORY_H #include "common/singletonpolicies.hpp" // several Policies usable together with SingletonFactory #include "common/util.hpp" #include "proc/nobugcfg.hpp" namespace lumiera { /** * 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_ */ template < class SI // the class of the Singleton instance , template class Create = singleton::StaticCreate // how to create/destroy the instance , template class Life = singleton::AutoDestroy // how to manage Singleton Lifecycle , template class Threading = singleton::IgnoreThreadsafety //TODO use Multithreaded!!! > class SingletonFactory { typedef typename Threading::VolatileType SType; typedef typename Threading::Lock ThreadLock; static SType* pInstance_; static bool isDead_; public: /** Interface to be used by SingletonFactory'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_) { ThreadLock guard SIDEEFFECT; if (!pInstance_) { if (isDead_) { Life::onDeadReference(); isDead_ = false; } pInstance_ = Create::create(); Life::scheduleDelete (&destroy); } } ENSURE (pInstance_); ENSURE (!isDead_); return *pInstance_; } private: /** @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() { TRACE (singleton, "Singleton: triggering destruction"); REQUIRE (!isDead_); Create::destroy (pInstance_); pInstance_ = 0; isDead_ = true; } }; // Storage for SingletonFactory's static fields... template < class SI, template class C, template class L, template class T > typename SingletonFactory::SType* SingletonFactory::pInstance_; template < class SI, template class C, template class L, template class T > bool SingletonFactory::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. ///// It seems this would either cost us much of the flexibility or get complicated ///// to a point where we could as well implement our own Depenency Injection Manager. } // namespace lumiera #endif