/* LIFECYCLEREGISTRY.hpp - registry for application lifecycle callbacks Copyright (C) Lumiera.org 2008, Christian Thaeter 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. */ /** @file lifecycleregistry.hpp ** Helper for registering lifecycle event callbacks, which are ** provided as a global service by lumiera::AppState. This service ** allows to enrol functions under a given label and then to call ** all those registered functions. ** @note this is in fact an event mechanism, and if we start using ** more than just this basic functionality, we should switch to ** boost::signals. (which has the downside of being an binary ** dependency). ** ** @see appstate.hpp */ #ifndef LUMIERA_LIFECYCLEREGISTRY_H #define LUMIERA_LIFECYCLEREGISTRY_H #include #include #include #include #include #include #include "lib/util.hpp" namespace lumiera { using boost::scoped_ptr; using boost::noncopyable; using std::tr1::function; using util::contains; using std::string; /** * Registry of callback functions accessible by a label (ID) * provided at registration. Registered functions will be added * to a list, which can be triggered via label. Used by AppState * to implement the lumiera lifecycle (init, shutdown) hooks. */ class LifecycleRegistry : private noncopyable { public: typedef void (*Hook)(void); typedef std::set Callbacks; typedef Callbacks::iterator Iter; /** @note only one copy of each distinct callback remembered */ bool enroll (const string label, Hook toCall) { return table_[label] .insert(toCall) .second; // true if actually stored } void execute (const string label) { Callbacks& cbs (table_[label]); Iter e = cbs.end(); for (Iter p = cbs.begin(); p != e; ++p) (*p)(); // invoke callback } /** get the (single) LifecycleRegistry instance. * @warning don't use it after the end of main()! */ static LifecycleRegistry& instance() // Meyer's singleton { static scoped_ptr theRegistry_; if (!theRegistry_) theRegistry_.reset (new LifecycleRegistry ()); return *theRegistry_; } private: std::map table_; LifecycleRegistry () { execute (ON_BASIC_INIT); // just to be sure, typically a NOP, because nothing is registered yet } ~LifecycleRegistry () {} friend void boost::checked_delete(LifecycleRegistry*); }; } // namespace lumiera #endif