MIRA
Singleton

Contents

Overview

The singleton pattern is a software design pattern that restricts the instantiation of a class to one single object - the singleton. It is useful when exactly one object of a certain class is needed and needs to be accessed globally, or where only one instance is allowed.

Singletons can be and should be used instead of global variables, since their initialization can be controlled better. Moreover, the singleton implementation ensures that there really exists only one instance. (When using global or static variables with Windows DLLs, there exists an instance of a global/static variable per DLL!)

The Singleton template class provides a very generic implementation of the singleton pattern.

There are two different ways to create a singleton for your class.

The preferred way is to subclass your class from the Singleton template class as follows:

class MyClassSingleton : public Singleton<MyClassSingleton>
{
public:
// Content of your class ...
void foo();
};

Please note that you have to specify the type of your class as first parameter of the Singleton template class.

The second way to use the Singleton allows you to use your class as both: a singleton, and a "normal" class that can be used to create several objects:

class MyClass
{
public:
// Content of your class ...
void foo();
};
// define a typedef that turns your class into a singleton
typedef Singleton<MyClass> MySingletonClass;

In both cases you can access your singleton by calling the instance() method:

MySingletonClass::instance().foo(); // calls the foo() method of the singleton

Please note, that this kind of usage is not allowed for the explicit singleton (see below).

The Singleton can be freely configured using policies that control the instantiation, creation and lifetime. The policies are specified as additional template parameters.

Instantiation Policy

The instantiation policy controls WHEN the singleton object is created. Currently, there are three different policies.

Lazy Instantiation

The LazyInstantiation policy is the default policy. It ensures that the singleton object will be instantiated only at the moment when the instance() method is called for the first time. If the instance() method is never called, the singleton will never be instantiated:

class MyClassSingleton :
public Singleton<MyClassSingleton, singleton::LazyInstantiation>
{
public:
// Content of your class ...
void foo();
};
...
MyClassSingleton::instance()... // the singleton will be created exactly at this point
...

For convenience, LazySingleton is provided to create singletons with lazy instantiation:

class MyClassSingleton : public LazySingleton<MyClassSingleton>
...

Eager Instantiation

The EagerInstantiation policy ensures early/eager instantiation, i.e. the singleton object will be instantiated BEFORE the first line of the applications main() function is executed. This is useful if the singleton must do some initialization as early as possible. Please note that the singleton will not be instantiated if the instance() method is never called!

class MyClassSingleton :
public Singleton<MyClassSingleton, singleton::EagerInstantiation>
{
public:
// Content of your class ...
void foo();
};
...
// the singleton will be already created at this point
...
MyClassSingleton::instance()... // even though the first instance call comes here
...

For convenience, EagerSingleton is provided to create singletons with eager instantiation:

class MyClassSingleton : public EagerSingleton<MyClassSingleton>
...

Explicit Instantiation

The ExplicitInstantiation policy allows full control of the construction and destruction time of the singleton. The singleton must be instantiated (and hence destroyed) explicitly by the user. It will throw XLogical, if someone tries to create a second instance of the singleton, or if someone tries to use the singleton instance when it was not yet created. Due to the explicit instantiation, this singleton type is the only singleton that allows to pass parameters to the constructor.

class MyClassSingleton :
public Singleton<MyClassSingleton, singleton::ExplicitInstantiation>
{
public:
// Content of your class ...
void foo();
};
...
MyClassSingleton::instance()... // EXCEPTION: no instance was created yet
MyClassSingleton myInstance; // explicit instantiation
MyClassSingleton::instance()... // OK: now it's allowed to access the instance, since the singleton was created before.
MyClassSingleton myInstance2; // EXCEPTION: can not create a second instance
...

For convenience, ExplicitSingleton is provided to create singletons with explicit instantiation:

class MyClassSingleton : public ExplicitSingleton<MyClassSingleton>
...

Creation Policy

The creation policy controls the way HOW singleton object is created. Currently, there are three different policies.

Create using new-operator

The CreateUsingNew policy uses the new/delete operators for creating/destructing the singleton object.

class MyClassSingleton :
public Singleton<MyClassSingleton, singleton::LazyInstantiation,
singleton::CreateUsingNew>
...

Create static

The CreateStatic policy creates the singleton object in static memory, i.e. without allocating memory. Instead, the memory is provided by the compiler at compile time.

class MyClassSingleton :
public Singleton<MyClassSingleton, singleton::LazyInstantiation,
singleton::CreateStatic>
...

Create using Allocator

The CreateUsing<...>::Allocator policy creates the singleton object using a custom allocator. The allocator must be specified as template parameter as follows:

class MyClassSingleton :
public Singleton<MyClassSingleton, singleton::LazyInstantiation,
singleton::CreateUsing<MyAllocator>::Allocator>
...

Lifetime Policy

The lifetime policy controls how singleton object is destructed. Currently, there are two different policies.

Normal Lifetime (C++ destruction order)

The NormalLifetime policy implements the normal C++ lifetime, i.e. singletons that are created first, are destroyed last.

class MyClassSingleton :
public Singleton<MyClassSingleton, singleton::LazyInstantiation,
singleton::CreateUsingNew, singleton::NormalLifetime>
...

No destruction (leaky singleton)

The NoDestroyLifetime policy never destroys the singleton object, i.e. the singleton's destructor will never be called. However, the occupied memory will be freed when the process terminates.

class MyClassSingleton :
public Singleton<MyClassSingleton, singleton::LazyInstantiation,
singleton::CreateUsingNew, singleton::NoDestroyLifetime>
...

Lock Policy

The lock policy controls the thread-safety when constructing the singleton. Currently, there are two different policies.

Locking using a mutex (the default)

The MutexLock policy ensures thread-safety when the singleton is instantiated, i.e. if two concurrent threads simultaneously access a singleton, that was not yet created.

class MyClassSingleton :
public Singleton<MyClassSingleton, singleton::LazyInstantiation,
singleton::CreateUsingNew, singleton::NormalLifetime,
singleton::MutexLock>
...

No Locking

The NoLock policy does not ensure any thread-safety. If two concurrent threads simultaneously access a singleton, that was not yet created, this may result in a multiple instantiation of the singleton class. However, if you can ensure, that a singleton is used by a single thread only or if at least the first instantiation of the singleton is guaranteed to be non-concurrent, you can use this policy, as it does not introduce any additional overhead.

class MyClassSingleton :
public Singleton<MyClassSingleton, singleton::LazyInstantiation,
singleton::CreateUsingNew, singleton::NormalLifetime,
singleton::NoLock>
...