Understanding Singletons

Why ANOTHER article about Singletons?

If you search for ‘Singleton’ in Google or StackOverflow you get a bajillion and a half results.  That makes sense, because it’s one of the most commonly implemented design patterns in the history of software.  Some reasons for the popularity of the Singleton are:

A.  It makes more intuitive sense to store things you want global access to in well-defined groupings, instead of having a bunch of globally namespaced functions, constants and variables you need to keep track of (read more about namespacing here).

B.  They are incredibly easy to implement.

Stick with me, by the end of this post you’ll have a much better understanding of the Singleton, and links to some other great reference materials.

So what are Singletons, exactly?

As you may know, computer science inherits a great many ideas from mathematics, and if you want to become a better programmer – and hope to someday call yourself a computer scientist, you must understand the mathematical foundations on which computer science has been built.  Fortunately, most of the concepts are pretty easy, including the Singleton.

A Singleton, as defined mathematically, is a set (a set could be similarly described as an array, linked list, vector, etc.) which has a cardinality of 1, meaning it only contains a single tuple, and that it cannot be subject to injective functions.  In plain English, this means that a set is only a Singleton if it:

A.  Only has one root level element.

B.  Has no siblings.

C.  Can not be cloned.

If it does not meet these requirements, it is not a Singleton.

As programmers, we commonly associate Singletons with single class instances (single objects), but they could also be other data types as well.  For example, some languages, such as Delphi, C# and Charm++, allow for read-only arrays, while C++ allows you to declare arrays and vectors as constant.  I’m sure there are many other examples.  I believe (though someone may correct me on this) – that those would also qualify as Singletons using the mathematical definition – provided they meet the aforementioned requirements.

Common uses of Singletons

Singletons are usually used by programmers when they want a class instance that is truly global – meaning that various classes and functions can perform operations on the instance, and see the changes the others make, without the need to pass a reference to that class around.

A. Logging: As opposed to procedural functions in the global namespace, “Logger” classes are commonly implemented as Singletons.

B.  Truly global classes: For example, keeping state.  Session and authentication management come to mind.

C.  Database instances: Singletons can in some cases reduce memory usage in your application because a single connection point to the database is established; a new instance is not created each time a query is made.

I’d love to hear some of the ways which you have implemented Singletons with satisfaction.

Criticisms

But what is a pattern if not also a suspected anti-pattern?  Singletons, despite their heavy usage, certainly have a fair amount of haters out there.  Some of these criticisms are simply FUD (fear, uncertainty and doubt) being passed from programmer to programmer like gonnorhea in a co-ed dorm; however, some are valid, and certainly need to be factored into design decisions.

A.  It’s hard to destroy a Singleton, and mishandling can cause very subtle and perhaps disastrous results.  Say, for example, that you want your program to destruct (shut down) in a very specific way.  You can’t really have a class destruct the Singleton, because hey, if the only class that can MAKE a Singleton is the Singleton itself, why should another class be able to destroy it?  And what happens if the class that destroys it kills it before another class, also dependent on the Singleton, can use data it depends on?  This rules out having other classes destroy Singletons.  So how about self destruction?  Well, depending on the language, compiler, and other variables, you may not have any control over what order objects are destroyed in.  When you only have one Singleton, this probably won’t cause an issue, but if you have many Singletons, each of which may depend on the data of the other, you may create the same problem faced in the previous example – you have dangling references to things that don’t exist anymore.  Not good!

This barely scratches the surface of this topic, for more I’d check out this article by John Vlissides, one of the original “Gang of Four” members, who spent most of his career as a researcher at IBM.

B.  Singletons can make testing, reuse and debugging painful.  Remember, since there is only one instance of a Singleton, if one class makes a change to a Singleton member – all other classes that use that data are now using that updated value.  Misko Hevery has written an amusing post on this topic here titled “Singletons are Pathological Liars.”

C.  Inheritance.  By definition, singletons cannot be used as base classes (ie child Extends Singleton).  However, some languages (such as C#) which support nested types.  Check out this post by John Skeet, a prominent C# developer and the author of “C# In Depth”, for more info on that.

Singletons and multithreading

Threads are spawned within the process created when a programming runs.  Multithreading allows a program to essentially “splinter off” and go in multiple directions simultaneously.   Concurrency problems occur when these threads are accessing shared resources and happen to collide.  One of the most intriguing bits I’ve read about Singletons was written by Vishal Kochhar.  He explains why the standard approach to Singletons is not threadsafe, and how mutual exclusion (a concept introduced by the late Edsger Djikstra, the Dutch computer scientist  who also gave us the modern pathfinding algorithm) can be implemented in C++ classes to ensure thread safety.  The article delves into many cool things – and I highly suggest you check it out.

Most scripting languages tell you that you need not worry about thread safety – that the language designers have ensured it – but if I was working on code that depended on thread safety, and was using Singletons, I’d probably double check. You need not worry about this in languages that do not use threads (such as JavaScript, unless you are using Web Workers – which DO in fact spawn threads).

Implementation in three languages

I implemented a Singleton class in 3 languages for fun and learning.

C++

#include <iostream>
#include <thread.h>

using namespace std;

class Singleton
{
	public:
		static int val_;
		static Singleton* instance() {
			if( val_ == 0 ) {
				//lock_mutex();
				if(p_instance == 0)
					new Singleton;
				//unlock_mutex();
				//MEMORY_BARRIER();
				val_ = 1;
				return p_instance;
			}
			else {
				return p_instance;
			}
		}

		void setMember(string& newState) {
			m_member = newState;
		}

		string getMember() {
			return m_member;
		}

	private:
		Singleton(){}

		static Singleton* p_instance;

		string m_member;
};

Singleton* Singleton::p_instance = 0;

int main()
{
	string newState = "active";
	Singleton::instance()->setMember(newState);
	cout << "Member has been set to:" << Singleton::instance()->getMember() << "\n";
	return 0;
}

Please note that the ideas for mutual exclusion were taken from the article written by Vishal Kochhar, which I have referenced.

JavaScript

var Singleton = (function()
{
	var instance = false;

	/*
	* Because this is in a closure, it cannot be accessed
	*/
	var member = 'test';

	function Constructor(){

		this.getMember = function(){
			return member;
		}

		this.setMember = function(v){
			member = v;
		}

	}

	/*
	* This is what's actually returned by the closure
	*/
	return new function(){

		this.getInstance = function() {	

			/*
			* Private member functions are accessible once the constructor has been called
			*/
			if(instance == false){
				instance = new Constructor();
				instance.constructor = null;
			}

			return instance;
		}

	}

}
)();

//print(Singleton.getInstance().getRand());
Singleton.getInstance().setMember('whatuppppp');

print(Singleton.getInstance().getMember());

Please note that this JavaScript implementation is almost certainly not a "real" singleton - it can be copied and passed around.

PHP


//Shows how a singleton can be used to keep state for the duration of a request
class Singleton
{
	private static $instance = 0;

	private static $member = null;

	/*
	 * Private constructor prevents object initialization ith new keyword
	*/
	private function __construct(){}

	/*
	 * Creates an instance - accesed statically since constructor is private
	*/
	public static function instance(){
		if(self::$instance)
		{
			return self::$instance;
		}

		//Return a new instance if one does not exist
		return new Singleton;
	}

	public function setMember($v){
		self::$member = $v;
	}

	public function getMember(){
		return self::$member;
	}

	/*
	 * Prevents cloning (ie copying the instance or using the clone keyword)
	*/
	public function __clone(){
		trigger_error('Singleton instance cannot be cloned.', E_USER_ERROR);
	}

	/*
	 * Prevents Unserializing of Object
	*/
	public function __wakeup(){
		trigger_error('Singleton instance cannot be unserialized.', E_USER_ERROR);
	}
}

class A
{
	public function __construct(){
		Singleton::instance()->setMember('active');
	}

	public function __toString(){
		return Singleton::instance()->getMember();
	}
}

class B
{
	public function __construct(){
	}

	public function __toString(){
		return Singleton::instance()->getMember();
	}
}

//Class A sets the member's value to 'active'
$a = new A;
echo "Member after being set by class A: $a \n \n";

//Class B simply returns the member value set by class A
$b = new B;
echo "Member after being returned by class B: $b \n \n";

Conclusion

Singletons are a popular pattern with both benefits and challenges associated with them. If you want to make use of this powerful pattern, ignore anyone who treats them as artifacts in a religious war and focus on understanding what they are, why and how they can be used.

Disclaimer

This post is essentially self-assigned homework.  I've written it to increase my own understanding of Singletons, their uses, limitations and theoretical underpinnings.  I hope this has helped you, but also hope you verify any assumptions I may have made, and point out any mistakes.

This entry was posted in C++, JavaScript, PHP, Programming. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

You must be logged in to post a comment.