Tag Archive for thread-safe

Implementing a Thread-Safe Singleton with C++11 Using Magic Statics

A couple of years ago I wrote a blogpost on how to write a thread-safe singleton using C++11. That implementation used std::call_once().

However, if your compiler is fully C++11 compliant, and by now, all major compilers are fully compliant, then the best way to implement a singleton is to use a magic static, as follows:

class CSingleton final
{
public:
	static CSingleton& GetInstance();

private:
	CSingleton() = default;
	~CSingleton() = default;

	CSingleton(const CSingleton&) = delete;
	CSingleton& operator=(const CSingleton&) = delete;
	CSingleton(CSingleton&&) = delete;
	CSingleton& operator=(CSingleton&&) = delete;
};

CSingleton& CSingleton::GetInstance()
{
	static CSingleton instance;
	return instance;
}

The most important change is the implementation of GetInstance() which now contains a local static variable (magic static). C++11 guarantees that this will be initialized in a thread-safe way.
I have now also marked the class as final, made the destructor non-virtual and private, and deleted the move constructor and move assignment operator.

Share

Implementing a Thread-safe Singleton with C++11

C++11 makes it easier to write a thread-safe singleton. Here is an example. The class definition of the singleton looks as follows:

#include <memory>
#include <mutex>

class CSingleton
{
public:
	virtual ~CSingleton() = default;
	static CSingleton& GetInstance();

private:
	static std::unique_ptr<CSingleton> m_instance;
	static std::once_flag m_onceFlag;
	CSingleton() = default;
	CSingleton(const CSingleton& src) = delete;
	CSingleton& operator=(const CSingleton& rhs) = delete;
};

The implementation of the GetInstance() method is very easy using C++11 std::call_once() and a lambda:

std::unique_ptr<CSingleton> CSingleton::m_instance;
std::once_flag CSingleton::m_onceFlag;

CSingleton& CSingleton::GetInstance()
{
	std::call_once(m_onceFlag,
		[] {
			m_instance.reset(new CSingleton);
	});
	return *m_instance.get();
}
Share