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();
	static CSingleton& GetInstance();

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

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

7 Comments so far »

  1. Sudo said,

    Wrote on October 21, 2012 @ 9:54 pm

    In C++11 thread-safety initialization and destruction is enforced in the standard. You don’t need to make use of std::once_flag or even std::unique_ptr.

  2. Marc Gregoire said,

    Wrote on October 22, 2012 @ 7:39 am

    If your compiler is 100% C++11 compliant, then you are correct. However, that is currently not yet the case. Take for example GCC, if you look on this page ( http://gcc.gnu.org/projects/cxx0x.html ) you can see that they don’t yet support the concurrency memory model and don’t yet support the “Dynamic Initialization and Destruction with Concurrency”, among other features.
    If you are absolutely sure your compiler supports those things, then you don’t need the call_once.
    However, if you are not 100% sure, I think it’s safer to use the call_once construct. If that compiles, then you know it will be thread-safe, unlike when you assume your compiler supports the new memory model, but it doesn’t, then you will introduce subtle multi-threading bugs.

  3. sellibitze said,

    Wrote on October 22, 2012 @ 9:13 am

    The singleton object may be destroyed to early. Consider a second singleton from another translation unit that makes use of this one even in its destructor. The deinitialization order of the static unique_ptr objects holding the singleton object adresses is unspecified.

  4. C said,

    Wrote on October 22, 2012 @ 8:17 pm

    I really like the choice for the std::once_flag flag. Will there be any support in C++11 for std::twice_flag flags etc?

  5. Marc Gregoire said,

    Wrote on October 22, 2012 @ 9:50 pm

    I’ve heard nothing about things like std::twice_flag.

    I’m wondering though, what are your use-cases for something like std::twice_flag?

  6. Francisco Almeida said,

    Wrote on October 23, 2012 @ 5:42 pm

    Since we’re using C++11 in the example, you could also delete the copy constructor and assignment operator. The compiler error obtained when trying to use a deleted member is a bit more expressive than when using a private member.

  7. Marc Gregoire said,

    Wrote on October 23, 2012 @ 5:53 pm

    100% correct about using the “delete” specifier on the copy constructor and the assignment operator.
    GCC does support it, but unfortunately, Visual C++ doesn’t support that feature yet, so I didn’t use it in this example.

Comment RSS · TrackBack URI

Leave a Comment

Name: (Required)

E-mail: (Required)

Website:

Comment: