New Fun Blog – Scott Bilas

Take what you want, and leave the rest (just like your salad bar).

Gem: An Automatic Singleton Utility

with 2 comments

From Game Programming Gems
Hardcover, Charles River Media, August 2000
Edited by Mark DeLoura

Introduction

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.

Definition

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.

Advantages

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.

The Problem

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.

Traditional Solution

The textbook solution to managing a singleton usually looks something like this:

[code lang="cpp"]
TextureMgr& GetTextureMgr()
{
static TextureMgr s_singleton;
return s_singleton;
}
[/code]

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.

A Better Way

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:

[code lang="cpp"]
class TextureMgr
{
static TextureMgr* ms_singleton;

public:
TextureMgr() { ms_singleton = this; /*...*/ }
~TextureMgr() { ms_singleton = 0; /*...*/ }

// ...

TextureMgr& GetSingleton() { return *ms_singleton; }
};
[/code]

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.

An Even Better Way

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:

[code lang="cpp"]
#include <cassert>

template <typename T> class Singleton
{
static T* ms_singleton;

public:
Singleton()
{
assert(!ms_singleton);
int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1;
ms_singleton = (T*)((int)this + offset);
}
~Singleton()
{ assert(ms_singleton); ms_singleton = 0; }
static T& GetSingleton()
{ assert(ms_singleton); return *ms_singleton; }
static T* GetSingletonPtr()
{ return ms_singleton; }
};

template <typename T> T* Singleton <T>::ms_singleton = 0;
[/code]

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:

[code lang="cpp"]
class TextureMgr : public Singleton <TextureMgr>
{
public:
Texture* GetTexture(const char* name);
// ...
};

#define g_TextureMgr TextureMgr::GetSingleton()

void SomeFunction()
{
Texture* stone1 = TextureMgr::GetSingleton().GetTexture("stone1");
Texture* wood6 = g_TextureMgr.GetTexture("wood6");
// ...
}
[/code]

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 0×1 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.

…Extra Note

(This section is not part of the original Gem.)

I’ve gotten a lot of feedback about the Singleton gem. Every single person wants to know why the hacky casting was necessary. One email I received from Jacob Marner stated it the best:

—————

Hi Scott,

I have just read your Gem in Game Programming Gems 1 about An Automatic Singleton Utility. In the last program you present the following constructor

[code lang="cpp"]
Singleton( void )
{
assert(!ms_singleton);
int offset = (int)(T*)1 - (int)(Singleton *)(T*)1;
ms_singleton = (T*)((int)this + offset);
}
[/code]

Although this constructor works as it should even under multiple inheritance, it is not portable (besides being quite ugly :) ). It is not generally allowed to cast a pointer to an integral and back again after manipulating it.

In it you assume that

  1. int use the same amount of bits as a pointer. This is not generally garanteed in C++.
  2. That a no extra information is needed to represent pointers – if for instance the memory model on the computer was segmented (like on the 80286) the code would fail if the base class and the derived class was in different segments.

I guess you don’t know that a pointer for a class in C++ actually also involves extra information about the pointer so it can easily navigate the class. What this means is that when you do a typecast for a class in C++ that involves multiple inheritance then the adress might change! Because of this we can simply replace the constructor with this simpler function that is portable and has the same functionality:

[code lang="cpp"]
Singleton( void )
{
assert( !ms_singleton );
ms_singleton = static_cast <T*> (this);
}
[/code]

What is important here is to note that “this” and “ms_singleton” will not end up having the same system adress if Singleton is a base class but not the first on derived.

—————

When I originally was experimenting with the recursive template singleton trick, it was on an earlier version of Visual C++ (5 I think). It was a long time ago, and I can’t remember clearly, but I believe I tried using a simple cast and it didn’t work. After a lot of attempts where I changed things a bit then recompiled to see what the disassembly looked like, I ended up with the hacky cast solution. I wasn’t concerned at all about portability, and like all things I work on, once it works and I’ve tested it, I move on to the next task and purge the old one from my cache.

So in short, on a modern compiler, heed Jacob’s words. On an older one, hacka hacka hacka until it works!

-Scott

August 20th, 2009 at 9:41 am

Posted in

2 Responses to 'Gem: An Automatic Singleton Utility'

Subscribe to comments with RSS or TrackBack to 'Gem: An Automatic Singleton Utility'.

  1. Hey! That’s not true!
    “So in short, on a modern compiler, heed Jacob’s words. On an older one, hacka hacka hacka until it works!”

    Well, I don’t know why! But when a singleton class is created on a dll and used in other dlls or executables, the singleton pointer will not always point to the right place on memory. Since each dll has its own heap (plz correct me if I’m wrong), mostly the singleton pointer used in another dll will point to a the same position on the second dll which creates first chance exception and most of the time a second chance exception too! But using this pattern will make sure the instance is just point to one place in all of the loaded dlls… Plz tell me why! I can’t understand it…

    Klaus

    5 Nov 11 at 3:58 am

  2. Sorry I can’t be helpful here. It’s been too long since I’ve messed around with C++ and DLL’s.

    Scott

    7 Jan 12 at 4:07 pm

Leave a Reply