I have seen many implementations of the singleton pattern all with their advantages and disadvantages. In this post I will describe how we implemented the singleton pattern in C++ for FireFly engine 1.0 and 2.0. The example code present in this post does not compile out of the box and is only meant to illustrate ideas.
The singleton pattern is a design pattern that makes sure that there is only one instantiation of a given object. This is particularly useful if there is a single object that performs actions for the entire system.
I actually think that this pattern is bad code practice but we use it nonetheless. The reason why I think it is bad is because from a design point of view there is no easy way to find what code actually uses the singleton since the singleton is part of the global state. The object is exposed everywhere in the code so it could be used everywhere.
Even though the singleton pattern could be seen as an anti pattern it has it uses. If there were no singletons, developers would have to pass the object around which, for object that are used a lot, is a pain in the ass.
Ok so for implementation details. ![]()
The first and simplest way is using a static function that returns the address to a static local variable:
class A {
public:
static A *GetInstance() {
static A instance;
return &instance;
}
}
This is a simple and elegant method but it gives you absolutely no control over when and how the singleton instance is instantiated and destroyed. A more robust way is to instantiate the singleton once and delete it when we are done with it. One way to achieve this is like so:
class B {
private:
static B *singleton;
public:
B() {
assert( singleton == 0 );
singleton = this;
}
~B() { singleton = 0; }
static B *GetInstance() { return singleton; }
}
With this method we have to explicitly instantiate B and we have to delete the class when we are done with it. However it gives us much more control over the entire process. However using this method involves a lot of code duplication. The singleton setup code is the same for every singleton class. We tackled this by defining macros that take care of declaration, implementation, construction and destruction.
class C {
__DeclareSingleton(C)
public:
C() {
__ConstructSingleton;
}
~C() {
__DestructSingleton;
}
}
The code in the example above is a lot more flexible. The defines remove the code duplication of the second example almost completely but not entirely. Fortunately there is another method that is described in Game Programming Gems 1. It involves a template class that wraps the singleton stuff. To make a class a singleton all one would have to do is derive from this template class like so:
class D : Singleton<D> {
}
This approach requires no additional effort from the programmer, it removes code duplication and we can implement the singleton class anyway we want. Lets take a look at the implementation of this singleton class:
template<class T>
class Singleton {
private:
static T *instance;
public:
Singleton() {
assert( instance == 0 );
int offset = (intptr_t)(T*)1 - (intptr_t)(Singleton*)(T*)1;
instance = (T*)((intptr_t)this+offset);
}
virtual ~Singleton() {
instance = 0;
}
static T *GetInstance() {
return instance;
}
}
The constructor looks very scary but does in fact nothing more than retrieving a pointer to T from the this pointer. This is only possible under the assumption that T is a subclass of the Singleton<T> class. What happens is that it first figures out the relative address of the derived class T and then stores the result in the instance pointer. The derived class could be deriving from more than just our Singleton<T> class, in which case the this pointer from our derived class might be different from the Singleton’s this. The solution is to take a nonexistent object at address 0×1 in memory, cast it to both types, and see what the difference is. The difference is the offset from the Singleton<T> to the derived class T. I just love the things you can do in C++! ![]()
Of course you can implement more methods than just the GetInstance method like for instance a method that returns a reference to the singleton or a method that checks it the singleton has been instantiated. All of these methods are trivial to implement. And because it is a separate class you can implement anything you like without having to modify code anywhere else.
So to conclude, I am very happy about our implementation of the singleton (anti-)pattern.


















