How to: convert any class to a Singleton with a template wrapper in C++

The singleton design pattern aims to give you a single instance of a class, and provide global access to it. Not two copies, not five, ONE copy – and one copy only. This is pretty useful when you have things in your code where you only ever want a single copy to exist, like a logging subsystem, or audio subsystem or what-have-you.

Why bother?

Why not just create a single instance of the class? Well yeah, you could, but where are you going to place the declaration? In the main so it’s globally declared? Global variables are bad-design like goto statements, and modern languages like C# don’t even have the facility to use global vars (deliberately removed to prevent misuse). Also, if you use a global instance it’s going to be instantiated as soon as the line of code to instantiate it is hit, which means you could be creating your instance (which might rely on other instances) before one of them is ready (for example, starting up a AI subsystem before a random number generator is seeded). You could swap initialisation orders around until you’re blue in the face, but it’s more work for you, and sooner or later you’re probably going to hit a chicken-and-egg scenario where one class requires another initialised first and vice-versa.

Okay, so how about a pointer to a static instance? This will define the object globally and defer instantiation until a time of your choosing, but you’re still using a global variable. And that’s something we really want to avoid. So what else is there? As you might have guessed, this whole tangle gets elegantly sorted out by the singleton design pattern.

Dinner for One

One of the best pages for singleton examples I’ve seen so far is this: http://www.yolinux.com/TUTORIALS/C++Singleton.html, and within the page they give a recipe for a templatised version so you can turn any class into a singleton which is responsible for its own instantiation and instance-limiting in a super-easy way – check it out:

#ifndef __SINGLETON_HPP_
#define __SINGLETON_HPP_
 
#include <iostream>
 
template <class T>
class Singleton
{
	public:
		// Return existing or create new instance
		static T* instance()
		{
			// Do we have an instance of this type? If so return it, otherwise create a new one.
			return m_pInstance ? m_pInstance : m_pInstance = new T;
		}
 
		// Manually destroy an existing instance. Call at end of program to clean up.
		static void destroy()
		{
			delete m_pInstance;
			m_pInstance = NULL;
		}
 
	private:
		Singleton();                            // Constructor                   (empty & cannot be called externally)
		~Singleton();                           // Destructor                    (empty & cannot be called externally)
		Singleton(Singleton const&);            // Copy constructor              (empty & cannot be called externally - no copies allowed)
		Singleton& operator=(Singleton const&); // Assignment operator           (empty & cannot be called externally - no assignment allowed)
		static T* m_pInstance;                  // Static template-type instance
};
 
// Set static instance value to NULL
template <class T> T* Singleton<T>::m_pInstance = NULL;
 
#endif

Dump the above into a file called Singleton.hpp and include it in your project – now let’s take it for a spin…

Example Usage

Once you’ve got your templated singleton wrapper (above), we can start applying it to some classes. The four main things we have to do are:

  1. Include our templated singleton wrapper, i.e.:
    #include "Singleton.hpp"
  2. Perform a global typedef (not global variable/object/instance – just a typedef) which creates us a templatised singleton version of our class(es) – i.e.:
    typedef Singleton<Logger> LoggerSubsystem;
  3. Access our instance via the SingletonTypedef::instance method, i.e.:
    LoggerSubsystem::instance()->openLogFile("LogFile.txt");
  4. And finally, destroy the instance before the program terminates, i.e.:
    LoggerSubsystem::destroy();

Here’s some example code which puts it all together with two simple place-holder classes:

#include <iostream>
#include <string>
#include <cstdlib>
 
#include "Singleton.hpp"
 
using namespace std;
 
// ----------------- Logger class --------------------------------
 
class Logger
{
	public:
		Logger()  { cout << "Creating logger..."   << endl; };
		~Logger() { cout << "Destroying logger..." << endl; };
 
		bool openLogFile(string theFilename);
		bool closeLogFile(string theFilename);
		bool writeToLogFile(string theFilename, string theData);
 
	private:
		//...
};
 
bool Logger::openLogFile(string theFilename)
{
	cout << "Opening log file: " << theFilename << endl;
	//...
	return true;
}
 
bool Logger::writeToLogFile(string theFilename, string theData)
{
	cout << "Writing " << theData << " to the file: " << theFilename << endl;
	// ...
	return true;
}
 
bool Logger::closeLogFile(string theFilename)
{
	cout << "Closing log file: " << theFilename << endl;
	// ...
	return true;
}
 
// ----------------- End of Logger class --------------------------------
 
// ----------------- App class --------------------------------
 
class App
{
	public:
		App()
		{
			cout << "Creating app..." << endl;
			uptimeInSeconds = 0;
			appData = (char*) malloc (1024 * 1024 * 150); // Allocate 150MB of RAM on the heap (to demonstrate we can free it)
		}
 
		~App()
		{
			cout << "Destroying app..." << endl;
			free(appData); // Release our 150MB of RAM
		}
 
		int getUptime();
		void tick();
 
	private:
		int uptimeInSeconds;
		char *appData; // Pointer to our allocated 150MB of RAM
};
 
int App::getUptime()
{
	return uptimeInSeconds;
}
 
void App::tick()
{
	uptimeInSeconds++;
}
 
// ----------------- End of App class --------------------------------
 
 
// Global declarations of templatised singleton typedefs (not instantiated until instance() is first called)
typedef Singleton<Logger> loggerSingleton;
typedef Singleton<App>    myApp;
typedef Singleton<App>    myApp2; // Create a second App singleton typedef to show that we never really do due to the singleton instance mechanism
 
 
int main()
{
	// Start off by trying to break stuff... as you do. The below can't be done because we've set the instance member
	// pointer as private, which forces us to use the ::instance method, which itself forces creation of our singleton.
	//cout << "here is a value: " << loggerSingleton::m_pInstance << endl;
 
	// Create a logger instance if it doesn't exist. Once an instance exists then use it instead of creating another instance
	loggerSingleton::instance()->openLogFile("LogFile.txt");
	loggerSingleton::instance()->writeToLogFile("AnotherFile.log", "abc123");
	loggerSingleton::instance()->closeLogFile("SomeOtherFile.txt");
 
	cout << endl << endl;
 
	// Create an app instance if it doesn't exist. Once an instance exists then use it instead of creating another instance.
	cout << "App uptime at start is: " << myApp::instance()->getUptime() << endl;
 
	// Add a tick to the uptime counter
	myApp::instance()->tick();
 
	// Display the uptime counter for our App instance
	cout << "App uptime after one tick is: " << myApp::instance()->getUptime() << endl;
 
	// Try to break things again using our second typedef that points to the same class as our "myApp" typedef. The uptime of the below
	// myApp2 singleton will be 1 (and not the default 0) because it's reusing myApp instead of creating myApp2 due to our Singleton template!
	cout << "Second app uptime is: " << myApp2::instance()->getUptime() << endl;
 
	// Destroy our singletons and release their resources
	myApp::destroy();
	loggerSingleton::destroy();
 
	return 0;
}

Pretty neat, huh?

Cleanup

As long as you remember to call the destroy function at the end of your code there’ll be no memory leaks or any “still reachable” memory for the OS to clean up. But how to be sure? Because if you valgrind the above code (via the alleyoop front-end, in this instance) you get this:

Alleyoop - No memory leak

Not too shabby at all.

Only, the thing is, during the creation of this article I’ve been reading things about Singletons. Bad things. Things that make me think they’re not the great idea I thought they were. Have a look at the article “Singleton, I love you but you’re bringing me down” over at CodingWithoutComments if you’re interested.

It seems that just a single instance of a class with a class factory to create the object (hence separating logic and instantiation) is really the way to go.

Oh well. It was nice while it lasted…