clean-up and comments for the singleton factory

This commit is contained in:
Fischlurch 2013-09-29 03:23:54 +02:00
parent 66b62e2146
commit 67523269fc
3 changed files with 57 additions and 27 deletions

View file

@ -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_)
{

View file

@ -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.");
}
};

View file

@ -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