Simple and Efficient Singleton Pattern

For game engines the singleton pattern is pretty commonly used for various global accesses, like for the core engine or for specific systems. Often times things like texture managers, the graphics implementation or a physical simulator are represented as singular entity that can be accessed globally.

A singleton pattern can be used to help facilitate and assert the existence of only one of these systems at any given time. This is important for a lot of code that is created under the assumption that only one given instance will be alive at once.

Advantages of Singletons

The biggest reason singletons are used is for code clarity. Any programmer that realizes something is a singleton is instantly informed of how it should be used. Beyond conceptual aids a singleton can also be an efficient means of allowing global access of an object. Often times in games everything is owned by something, otherwise referred to as the “Ownership Pattern”.

If a game consists purely of things owning other things (except for the core Game or Engine object), retrieving different systems from global access might be hard. This is because the Engine would be the only global thing. Code like this:

is long and annoying and also inefficient; there are many unnecessary levels of indirection. Instead a singleton can be used to solve such a problem.

A Traditional Approach

The traditional approach to creating a singleton is to utilize some code like so:

This approach does in fact ensure that only a single instance of a given class is alive at any given time, and can be especially effective if the constructor and destructor are declared in the private section.

Drawbacks

There is a pretty big drawback to this traditional style: construction and destruction order. C++ makes no guarantee about the construction and destruction order of objects on global (file) scope. This means that the code run for each destructor of every singleton instance (despite construction time) can run in any order.

This poses a huge problem for systems that depend on one another. What if the TextureManager class contained a pointer to the Graphics class? What if the destructor of the TextureManager tries to access the Graphics pointer and the Graphics singleton has already destructed?

Such an issue does have workaround solutions, but it might be best to have some form of singleton that controls construction and destruction explicitly.

A Better Singleton

Here’s a simple way to implement a singleton and allow explicit construction and destruction:

This singleton is actually quite safe due to the simple assertion in the constructor. The nice thing about this assertion is that it can be compiled away during release builds. This might be considered an advantage against the traditional approach, as the traditional approach will often times have a boolean flag to test for previous construction (in the assembly of the compiled C++).

Since it is a slight inconvenience to add the instance handling to every class you wish to be a single the use of a template mixin can help. Making such a utility can be tricky due to multiple inheritance. I will leave solving the multiple inheritance issue as an exercise for the reader.

I myself use this sort of singleton (I don’t even have a utility) and enjoy it. I actually don’t even use a Get function but just have a global extern’d pointer in my header.

I’ve also seen this exact implementation in a few areas, one of which is in an article by Scott Bilas in the first Game Programming Gems book (he covers the multiple inheritance issue),

TwitterRedditFacebookShare

4 thoughts on “Simple and Efficient Singleton Pattern

  1. Adrian L.

    Hi! I read a couple of your previous posts and some of them were interesting but a lot of the stuff seems more of an art for itself then really solving serious problems. In fact singleton is perfect example of wasting time and effort and adding impractical code that later on needs maintenance and more code needs more time (= money)

    If global access to an instance of a class is needed just make it global. One problem that singletons are suposedly solve  is ensuring that only one instance of given class is created, and that might be required if having more instances just messes up with the state of the application. But this, on the other hand is just a symptom of bad design in my opinion. The second problem with the ‘traditional’ appraoch is that it is not thread-safe. Of course since C++11 it is but not everyone has the luxury to target C++11 just yet. Last thing to note is that your last solution to singleton in fact is not a singleton at all. You have public ctor so you can create multiple instances. Assertion should be for sanity checks not as error catching mechanism as these are stripped out from release builds.
    Besides I believe that the assertion has a typo and you meant: assert( s_instance == NULL );

    The fact that you, yourself ended up with wrapping it with global pointer should be enough to say that singletons are just bad trolling in disguise.

    Also regarding the initialization fiasco etc. You can just have one function called InitializeEngine or something similar that ensures proper object creation, initialization of the engine subsystems and wire-ing up everything. Then you don’t have problems with what gets initialized first.

    Reply
    1. Randy Gaul Post author

      Hi, thanks for the comment. I tried to express that really all I was after was the ability to track an object in a simple way, and control its lifetime explicitly. I don’t mind if you (or others) don’t really think this is a “singleton”, and I can understand reasons to disagree here. Maybe you know of a different name or term?

      This article presents just one way to provide access to something. Whether or not the choice to do so is good programming practice is out of scope of my knowledge.

      One thing to consider is the syntactical clarity that can arise from retrieving something from a Get( ) function. It can be understood by all engineers working with the code that this gives immediate hints as to how to use the object in question. I feel this can be a positive regardless of whether or not using a global is “bad design”, and maybe this positive aspect is sometimes overlooked.

      As for the usage of asserts in this way: to me it should be fine if creating multiple instances is considered a programming bug. The goal was just to track an object in a simple way, not strictly enforce lifetime management. I actually wanted to free lifetime management. In this way I feel using a simple debug assert to catch a programming error (or put in other terms, a sanity check, implying that it would be ridiculous for an engineer to try to make another instance) becomes a good way to make sure nobody is being stupid.

      It is also interesting that you don’t find some of my content practical, as I haven’t actually written an article about something I didn’t implement myself and find useful. Usually I learn these topics from other people who have proven the merit of the topics I write about. This is why you see a lot of my articles begin by thanking other people for their contributions.

      Reply
  2. teodron

    I second the opinion on this design not being as robust as needed. Having runtime mechanisms enforce the correct usage of this object kind of defeats the purpose of this pattern – force the programmer not to construct it by hand wherever they feel like, but use the static accessor.

    As for it not being threadsafe, adding a simple autolock after checking that there’s no instance created should work smoothly. But it might confuse the more novice programmers to see such “magic” along with the simplest pattern of them all.

    The rest is just philosophical debate on how bad singletons are. People, wake up, there are much more idiotic and common-sense defying idioms and constructions in a game engine, it would make your eyes bleed. Don’t believe me? Then you’re either a smart-ass guru or haven’t worked with an engine and game totaling at least 1 million lines of code (excluding middleware!).

    Keep up the job.. cause it’s not bad at all! Just be more explicit and emphasize the plus and minuses of your coding designs. you’ll enlighten more people and keep away redundant criticism.

    Reply
    1. Randy Gaul Post author

      Hi there, thanks for the nice comment! I would agree that if your purpose is to enforce singleton usage of an object then the implementation in this post is not really the ideal way to go about so. It really is just a matter of what is trying to be accomplished. I imagine in smaller projects having convenient and simple ways to track a global system is much more important than enforcing strict life-time management.

      I appreciate the feedback.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *