Gem: An Automatic Singleton Utility
By Scott Bilas
![]()
This gem presents an easy and safe method to provide access to a C++ class singleton while retaining control over when it is instantiated and destroyed.
A singleton is an object that only has one instance in a system at any time. Some common examples of singletons in games are managers for texture maps, files, or the user interface. Each is a subsystem that’s generally assumed to be available once the game has started up and will stay in existence until the game shuts down.
Some of these subsystems may be implemented using global functions and static variables. An example of this would be a memory manager’s malloc() and free() functions. These types of subsystems are not “singletons” in that they don’t have their functionality encapsulated into a class and can’t be represented using a single instance of that class. There’s no reason a memory manager like this couldn’t be converted into a class and used as a singleton, but this isn’t common.
An example of a singleton is a texture map manager. It may be called TextureMgr and would have methods such as GetTexture() and UseTexture(). Its purpose would be to find texture maps in the file store, convert them to system graphics objects, make them available to the rasterizer(s), and own them until they are no longer needed, at which point it deletes them. Only one instance of TextureMgr will be needed in the system so this class would naturally be used as a singleton.
What’s the point of singletons? First they provide conceptual clarity, as labels are very important. Calling a class a singleton and following a naming convention (such as -Mgr, -Api, Global-, etc.) relates important details about how we intend that class to be used.
Singletons also provide notational convenience. Every object in a C++ system must be owned by something. The ownership pattern of these objects depends on the game, but often resembles a multi-level hierarchy, where each higher level owns a set of child objects, each of which in turn may own child objects. Each object publishes a set of functions to access its children. For example, to get at the TextureMgr instance, you may need to call a sequence of functions such as GetApp()‑>GetServices()‑>GetGui()‑>GetTextureMgr(), where each function returns a pointer to the requested child object. This is inconvenient and not exactly efficient, considering the multiple dereferences. Singletons can solve this problem because they are treated as global objects.
Well then why not just use global objects? They are certainly convenient – the TextureMgr object could be accessed through a g_TextureMgr object reference that has been declared with external linkage at global scope (or within a namespace), or perhaps through a function that returns a reference to that object instead. However, the construction and destruction order of global objects is implementation dependent and generally impossible to predict in a portable manner.
There are workarounds to all these problems, but what we really want is a way to have the convenience advantage of treating a singleton like a global object, without the inconvenience of losing control over when and where it gets constructed and destroyed.
The textbook solution to managing a singleton usually looks something like this:
TextureMgr& GetTextureMgr( void )
{
static T s_Singleton;
return ( s_Singleton );
}
There are many variations that use templates and macros for notational convenience, but the effect is still the same. This allows a singleton to only be instantiated on demand – the first time this function is called. It’s convenient to use, but leaves its destruction up to the compiler, and requires that it only be done at application shutdown time. We need more control than that. Order of destruction is very important in a game, in that some subsystems must be shut down and destroyed before others. Also, what if we want to shut down only part of the game while it’s still running? This is impossible with this solution.
All we’re really after is the ability to track a singleton, and for that what we need is a pointer to it. What if we were to do something like this:
class TextureMgr
{
static TextureMgr* ms_Singleton;
public:
TextureMgr( void ) { ms_Singleton = this; /*...*/ }
~TextureMgr( void ) { ms_Singleton = 0; /*...*/ }
// ...
TextureMgr& GetSingleton( void ) { return ( *ms_Singleton ); }
};
Add a few assertions for safety purposes and this would work! We can now construct and destroy a TextureMgr wherever we like, and accessing the singleton is as simple as calling TextureMgr::GetSingleton(). But this is still a little inconvenient, given that the same code (to track the singleton pointer) needs to be added to every singleton class.
A more generic solution would be to use templates to automatically define the singleton pointer and do the work of setting it, querying it, and clearing it. It can also check (through assert) to make sure that we aren’t accidentally instantiating more than one. Best of all, we can get all of this functionality for free just by deriving from this simple little class:
#include <cassert>
template <typename T> class Singleton
{
static T* ms_Singleton;
public:
Singleton( void )
{
assert( !ms_Singleton );
int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1;
ms_Singleton = (T*)((int)this + offset);
}
~Singleton( void )
{ assert( ms_Singleton ); ms_Singleton = 0; }
static T& GetSingleton( void )
{ assert( ms_Singleton ); return ( *ms_Singleton ); }
static T* GetSingletonPtr( void )
{ return ( ms_Singleton ); }
};
template <typename T> T* Singleton <T>::ms_Singleton = 0;
To convert any class into a singleton, you only need to do these three easy steps:
1. Publicly derive your class MyClass from Singleton <MyClass>.
2. Make sure that you’re constructing an instance of MyClass somewhere in the system before using it. How you instantiate it doesn’t matter. You can let the compiler worry about it by making it a global or local static, or you can worry about it yourself via new and delete through an owner class. Regardless of how and when you construct the instance, it will get tracked and may be used as a singleton through a common interface by the rest of the system.
3. Call MyClass::GetSingleton() to use the object from anywhere in the system. If you’re lazy like me, you can #define g_MyClass to be MyClass::GetSingleton() and treat it exactly like a global object for notational convenience.
Here is a sample usage of the class:
class TextureMgr : public Singleton <TextureMgr>
{
public:
Texture* GetTexture( const char* name );
// ...
};
#define g_TextureMgr TextureMgr::GetSingleton()
void SomeFunction( void )
{
Texture* stone1 = TextureMgr::GetSingleton().GetTexture( “stone1” );
Texture* wood6 = g_TextureMgr.GetTexture( “wood6” );
// ...
}
The Singleton class’s only purpose in life is to automatically register and unregister any instance of its derived (MyClass) type as it is constructed and destroyed. We’re deriving MyClass from Singleton <MyClass> purely to inherit this convenient functionality. This doesn’t affect the size of the class in any way – it only adds some automatic function calls.
So how does this work? All of the important work is done in the Singleton constructor, where it figures out the relative address of the derived instance and stores the result in the singleton pointer (ms_Singleton). Note that the derived class could be deriving from more than just the Singleton, in which case “this” from MyClass might be different from the Singleton “this”. The solution is to take a nonexistent object sitting at address 0x1 in memory, cast it to both types, and see what the difference is. This will effectively be the distance between Singleton <MyClass> and its derived type MyClass, which it can use to calculate the singleton pointer.