Home > C++, Design > 3 simple ways to create singleton pattern in C++

3 simple ways to create singleton pattern in C++

In my previous posts (part 1 and part 2), I’ve presented singleton design pattern implementation in C# .NET. In order to complete the subject, I would like to present singleton pattern implementation in old good native C++.

1) Basic singleton: static function “GetInstance” provides the access point; constructor, copy constructor and operator= are hidden from the user. The singleton is allocated upon first demand (lazy initialization). Null pointer is used to constrol first access, hence must be initialized in a C++ way – out of the class (as a static member).

class CKeyboard
{
public:
	static CKeyboard* GetInstance() 
	{
		if (!m_pInstance)
			m_pInstance = new CKeyboard();
		return m_pInstance;
	}

private:
	CKeyboard() {}
	CKeyboard(const CKeyboard&);
	CKeyboard& operator=(const CKeyboard&); 

private:
	static CKeyboard *m_pInstance;
};

CKeyboard* CKeyboard::m_pInstance = NULL;

2) Meyers singleton: in this implementation, first creation is “delegated” to the compiler, using “static” keyword within function. This way provies well-known creation point for static variable. Note, that “GetInstance” access function’s return value is a reference rather then pointer (as in previous example). Working with a reference is better: now user can not delete the singleton’s pointer. In addition, this implementation is so simple!

class CKeyboard
{
public:
	static CKeyboard& GetInstance()
	{
		static CKeyboard keyboard;
		return keyboard;
	}

private:
	CKeyboard() {}
	CKeyboard(const CKeyboard&);
	CKeyboard& operator=(const CKeyboard&);
};

3) Singleton inheritance: sometimes one needs to inherit from singleton class. This is not trivial thing, because static function can not be overriden. One can add “GetInstance2” function in order to create the inherited object, but for sure this solution is very bad: user can call the wrong function. Better solution is achived using C++ templates: the required type is passed as a template parameter. Note: this is not a way to create universal singleton. Rather, this way allows to create a singleton class inside some infrastructure, and to extend it apropriately to user’s needs. This singleton is base om Meyers singleton:

template<class T>
class CKeyboard
{
public:
	static T& GetInstance()
	{
		m_bSingletonCreating = true;
		static T keyboard;
		m_bSingletonCreating = false;
		
		return keyboard;
	}

protected:
	CKeyboard() {}
	CKeyboard(const CKeyboard&);
	CKeyboard& operator=(const CKeyboard&);

	static bool m_bSingletonCreating;
};

// Static variable initialization
template<class T>
bool CKeyboard<T>::m_bSingletonCreating = false;

class CUSBKeyboard : public CKeyboard<CUSBKeyboard>
{
public: 
	CUSBKeyboard () 
	{
		if (!m_bSingletonCreating)
			throw "Singleton must not be initialized";

		//...
	}
};

Those are 3 possible implementations of singleton , I wanted to present. Do you know more? Please share your solution with us…

Categories: C++, Design Tags: , ,
  1. Vlad
    April 3rd, 2011 at 23:14 | #1

    All 3 implementations are not thread safe. In order to create a true singleton you need to implement critical section in GetInstance method.
    There is a simple implementation with single check and the most accurate with dual check.

    For instance, here is a smart method:
    static CKeyboard* GetInstance()
    {
    if (!m_pInstance)
    {
    EnterCriticalSection(&critSect);
    if (!m_pInstance)
    m_pInstance = new CKeyboard();
    LeaveCriticalSection(&critSect);
    }
    }
    return m_pInstance;
    }

  2. GenEric
    April 17th, 2011 at 00:58 | #2

    You are definitely right about 1 implementation, but regarding to 2 and 3 I don’t think so. 2 and 3 are thread-safe in a new C++ standard – they use static inside a function.

  3. Gareth
    May 17th, 2011 at 20:32 | #3

    Even this is not thread safe on a mulit-core system because the CPU can reorder write operations and the m_pInstance may be set before the CKeyboard has been properly constructed. The writes are only guaranteed after the LeaveCriticalSection which contains a memory barrier.

    To be fully thread safe you can introduce your own memory barrier by using a temporary variable to create the object, perform a memory barrier and then assign to m_pInstance before leaving the critical section. Alternatively you can use InterlockedExchange to perform the same thing:

    static CKeyboard* GetInstance()
    {
    if (!m_pInstance)
    {
    EnterCriticalSection(&critSect);
    if (!m_pInstance)
    InterlockedExchange ((LONG*)&m_pInstance, (LONG)new CKeyboard());
    LeaveCriticalSection(&critSect);
    }
    }
    return m_pInstance;
    }

  4. GenEric
    May 18th, 2011 at 22:09 | #4

    Thank you for pointing to this problematic thing.

    Indeed, multi-core systems have not got an attention in current post. In multi-core systems, the raise conditions are more complicated: several CPUs, several caches etc.
    Becase of multi-core system behaviour, Syngleton Pattern is sometimes reffered as “anti-pattern”, and is not recommended for use.

    If you have an expirience of working with multi-core system, you are invited to write a post in our blog. It is very interesting and complicated subject.

  5. akis
    May 24th, 2011 at 12:06 | #5

    GenEric :You are definitely right about 1 implementation, but regarding to 2 and 3 I don’t think so. 2 and 3 are thread-safe in a new C++ standard – they use static inside a function.

    do you have examples of this? I have checked with VS2010 and GCC 4.5.2/4 and there is nto much there in terms of protection

  1. December 3rd, 2011 at 01:19 | #1