clean-up and comments for the singleton factory
This commit is contained in:
parent
66b62e2146
commit
67523269fc
3 changed files with 57 additions and 27 deletions
|
|
@ -22,7 +22,7 @@
|
|||
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:
|
||||
Loki code accompanies the book:
|
||||
Alexandrescu, Andrei. "Modern C++ Design: Generic Programming
|
||||
and Design Patterns Applied".
|
||||
Copyright (c) 2001. Addison-Wesley. ISBN 0201704315
|
||||
|
|
@ -38,8 +38,6 @@ This code is heavily inspired by
|
|||
#include "lib/singleton-policies.hpp" // several Policies usable together with SingletonFactory
|
||||
|
||||
#include "lib/nobug-init.hpp"
|
||||
#include "include/logging.h"
|
||||
#include "lib/util.hpp"
|
||||
#include "lib/sync-classlock.hpp"
|
||||
|
||||
namespace lib {
|
||||
|
|
@ -82,7 +80,7 @@ namespace lib {
|
|||
{
|
||||
if (!pInstance_)
|
||||
{
|
||||
ThreadLock guard SIDEEFFECT;
|
||||
ThreadLock guard;
|
||||
|
||||
if (!pInstance_)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
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:
|
||||
Loki code accompanies the book:
|
||||
Alexandrescu, Andrei. "Modern C++ Design: Generic Programming
|
||||
and Design Patterns Applied".
|
||||
Copyright (c) 2001. Addison-Wesley. ISBN 0201704315
|
||||
|
|
@ -46,8 +46,8 @@ namespace singleton {
|
|||
|
||||
/* === several Policies usable in conjunction with lib::Singleton === */
|
||||
|
||||
/**
|
||||
* Policy placing the Singleton instance into a statically allocated buffer
|
||||
/**
|
||||
* Policy to place the Singleton instance into a statically allocated buffer
|
||||
*/
|
||||
template<class S>
|
||||
class StaticCreate
|
||||
|
|
@ -91,11 +91,29 @@ namespace singleton {
|
|||
* Policy relying on the compiler/runtime system for Singleton Lifecycle
|
||||
*/
|
||||
template<class S>
|
||||
struct AutoDestroy
|
||||
class AutoDestroy
|
||||
{
|
||||
class DeleteTrigger
|
||||
{
|
||||
vector<DelFunc> dels_;
|
||||
|
||||
public:
|
||||
void schedule (DelFunc del)
|
||||
{
|
||||
dels_.push_back(del);
|
||||
}
|
||||
~DeleteTrigger()
|
||||
{
|
||||
vector<DelFunc>::iterator del = dels_.begin();
|
||||
for ( ; del != dels_.end(); ++del )
|
||||
(*del)(); // invoke deleter function
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
/** implements the Singleton removal by calling
|
||||
* the provided deleter function(s) at application shutdown,
|
||||
* relying on the runtime system calling destructors of static
|
||||
* relying on the runtime system to call destructors of static
|
||||
* objects. Because this Policy class can be shared between
|
||||
* several Singletons, we need to memorise all registered
|
||||
* deleter functions for calling them at shutdown.
|
||||
|
|
@ -103,23 +121,6 @@ namespace singleton {
|
|||
static void
|
||||
scheduleDelete (DelFunc kill_the_singleton)
|
||||
{
|
||||
class DeleteTrigger
|
||||
{
|
||||
vector<DelFunc> dels_;
|
||||
|
||||
public:
|
||||
void schedule (DelFunc del)
|
||||
{
|
||||
dels_.push_back(del);
|
||||
}
|
||||
~DeleteTrigger()
|
||||
{
|
||||
vector<DelFunc>::iterator i = dels_.begin();
|
||||
for ( ; i != dels_.end(); ++i )
|
||||
(*i)(); // invoke deleter function
|
||||
}
|
||||
};
|
||||
|
||||
REQUIRE (kill_the_singleton);
|
||||
static DeleteTrigger finally;
|
||||
finally.schedule (kill_the_singleton);
|
||||
|
|
@ -128,7 +129,7 @@ namespace singleton {
|
|||
static void
|
||||
onDeadReference ()
|
||||
{
|
||||
throw lumiera::error::Logic ("Trying to access the a Singleton instance that has "
|
||||
throw lumiera::error::Logic ("Trying to access a Singleton instance that has "
|
||||
"already been released or finished its lifecycle.");
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,6 +22,12 @@
|
|||
|
||||
/** @file singleton.hpp
|
||||
** Factory for creating Singleton instances.
|
||||
** The <b>Singleton Pattern</b> provides a single access point to a class or
|
||||
** service and exploits this ubiquitous access point to limit the number of objects
|
||||
** of this type to a single shared instance. Within Lumiera, we mostly employ a
|
||||
** factory template; the intention is to use on-demand initialisation and a
|
||||
** standardised lifecycle.
|
||||
**
|
||||
** This configuration header just pulls in some other implementation headers in
|
||||
** the right order. The basic class template for creating singletons resides in
|
||||
** singleton-factory.hpp, besides we need policy classes defining how to create
|
||||
|
|
@ -32,6 +38,31 @@
|
|||
** You'll find the default Policies in singleton-factory.hpp and the default
|
||||
** definition of type lumiera::singleton in singleton-preconfigure.hpp
|
||||
**
|
||||
** \par Why Singletons? Inversion-of-Control and Dependency Injection
|
||||
**
|
||||
** Singletons are frequently over-used, and often they serve as disguised
|
||||
** global variables to support a procedural programming style. As a remedy, typically
|
||||
** the use of a »Dependency Injection Container« is promoted. And -- again typically --
|
||||
** these DI containers tend to evolve into heavyweight universal tools and substitute
|
||||
** the original problem by metadata hell.
|
||||
**
|
||||
** Thus, for Lumiera, the choice to use Singletons was deliberate: we understand the
|
||||
** Inversion-of-Control principle, yet we want to stay just below the level of building
|
||||
** a central application manager core. At the usage site, we access a factory for some
|
||||
** service <i>by name</i>, where the »name« is actually the type name of an interface
|
||||
** or facade. Singleton is used as an implementation of this factory, when the service
|
||||
** is self-contained and can be brought up lazily.
|
||||
**
|
||||
** \par Conventions, Lifecycle and Unit Testing
|
||||
**
|
||||
** Usually we place an instance of the singleton factory (or some other kind of factory)
|
||||
** as a static variable within the interface class describing the service or facade.
|
||||
** As a rule, everything accessible as Singleton is sufficiently self-contained to come
|
||||
** up any time -- even prior to \c main(). But at shutdown, any deregistration must be
|
||||
** done explicitly using a lifecycle hook. Destructors aren't allowed to do any significant
|
||||
** work besides releasing references, and we acknowledge that singletons can be released
|
||||
** in \em arbitrary order.
|
||||
**
|
||||
** @see SingletonFactory
|
||||
** @see singleton::StaticCreate
|
||||
** @see singleton::AutoDestroy
|
||||
|
|
|
|||
Loading…
Reference in a new issue