This article offers some insight into singleton design-pattern.

The singleton pattern is a design pattern used to implement the mathematical concept of a singleton, by restricting the instantiation of a class to one object. The GoF book describes the singleton as: “Ensure a class only has one instance, and provide a global point of access to it.

The Singleton design pattern is not as simple as it appears at a first look and this is proven by the abundance of Singleton discussions and implementations. That’s way I’m trying to figure a few implementations, some base on C++ 11 features (smart pointers and locking primitives as mutexs). I am starting from, maybe, the most basic singleton implementation trying to figure different weaknesses and tried to add gradually better implementations.

The basic idea of a singleton class implies using a static private instance, a private constructor and an interface method that returns the static instance.

Version 1

Maybe, the most common and simpler approach looks like this:

class simpleSingleton { simpleSingleton(); static simpleSingleton* _pInstance; public: ~simpleSingleton() {} static simpleSingleton* getInstance() { if (!_pInstance) { _pInstance = new simpleSingleton(); } return _pInstance; } void demo() { std::cout << "simple singleton # next - your code ..." << std::endl; } } simpleSingleton* simpleSingleton::_pInstance = nullptr; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class simpleSingleton { simpleSingleton ( ) ; static simpleSingleton * _pInstance ; public : ~ simpleSingleton ( ) { } static simpleSingleton * getInstance ( ) { if ( ! _pInstance ) { _pInstance = new simpleSingleton ( ) ; } return _pInstance ; } void demo ( ) { std :: cout << "simple singleton # next - your code ..." << std :: endl ; } } simpleSingleton * simpleSingleton :: _pInstance = nullptr ;

Unfortunately this approach has many issues. Even if the default constructor is private, because the copy constructor and the assignment operator are not defined as private the compiler generates them and the next calls are valid:

// Version 1 simpleSingleton * p = simpleSingleton::getInstance(); // cache instance pointer p->demo(); // Version 2 simpleSingleton::getInstance()->demo(); simpleSingleton ob2(*p); // copy constructor ob2.demo(); simpleSingleton ob3 = ob2; // copy constructor ob2.demo(); 1 2 3 4 5 6 7 8 9 10 11 // Version 1 simpleSingleton * p = simpleSingleton :: getInstance ( ) ; // cache instance pointer p->demo(); // Version 2 simpleSingleton :: getInstance ( ) -> demo ( ) ; simpleSingleton ob2 ( * p ) ; // copy constructor ob2 . demo ( ) ; simpleSingleton ob3 = ob2 ; // copy constructor ob2 . demo ( ) ;

So we have to define the copy constructor and the assignment operator having private visibility.

Version 2 – Scott Meyers version

Scott Meyers in his Effective C++ book adds a slightly improved version and in the getInstance() method returns a reference instead of a pointer. So the pointer final deleting problem disappears.

One advantage of this solution is that the function-static object is initialized when the control flow is first passing its definition.

class otherSingleton { static otherSingleton * pInstance; otherSingleton (); otherSingleton(const otherSingleton& rs) { pInstance = rs.pInstance; } otherSingleton& operator = (const otherSingleton& rs) { if (this != &rs) { pInstance = rs.pInstance; } return *this; } ~otherSingleton (); public: static otherSingleton& getInstance() { static otherSingleton theInstance; pInstance = &theInstance; return *pInstance; } void demo() { std::cout << "other singleton # next - your code ..." << std::endl; } }; otherSingleton * otherSingleton::pInstance = nullptr; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class otherSingleton { static otherSingleton * pInstance ; otherSingleton ( ) ; otherSingleton ( const otherSingleton & rs ) { pInstance = rs . pInstance ; } otherSingleton & operator = ( const otherSingleton & rs ) { if ( this != &rs ) { pInstance = rs . pInstance ; } return * this ; } ~ otherSingleton ( ) ; public : static otherSingleton & getInstance ( ) { static otherSingleton theInstance ; pInstance = &theInstance ; return * pInstance ; } void demo ( ) { std :: cout << "other singleton # next - your code ..." << std :: endl ; } } ; otherSingleton * otherSingleton :: pInstance = nullptr ;

The destructor is private in order to prevent clients that hold a pointer to the Singleton object from deleting it accidentally. So, this time a copy object creation is not allowed:

otherSingleton ob = *p; ob.demo(); 1 2 otherSingleton ob = * p ; ob . demo ( ) ;



error C2248: otherSingleton::otherSingleton ' : cannot access private member declared in class 'otherSingleton'

error C2248: 'otherSingleton::~otherSingleton' : cannot access private member declared in class 'otherSingleton'



but we can still use:

// Version 1 otherSingleton *p = &otherSingleton::getInstance(); // cache instance pointer p->demo(); // Version 2 otherSingleton::getInstance().demo(); 1 2 3 4 // Version 1 otherSingleton * p = &otherSingleton :: getInstance ( ) ; // cache instance pointer p->demo(); // Version 2 otherSingleton :: getInstance ( ) . demo ( ) ;

This singleton implementation was not thread-safe until the C++ 11 standard. In C++11 the thread-safety initialization and destruction is enforced in the standard.

If you’re sure that your compiler is 100% C++11 compliant then this approach is thread-safe. If you’re not such sure, please use the approach version 4.

Multi-threaded environment

Both implementations are fine in a single-threaded application but in the multi-threaded world things are not as simple as they look. Raymond Chen explains here why C++ statics are not thread safe by default and this behavior is required by the C++ 99 standard.

The shared global resource and normally it is open for race conditions and threading issues. So, the singleton object is not immune to this issue.

Let’s imagine the next situation in a multithreaded application:

static simpleSingleton* getInstance() { if(!pInstance) // 1 { pInstance = new simpleSingleton(); // 2 } return pInstance; // 3 } 1 2 3 4 5 6 7 8 9 static simpleSingleton * getInstance ( ) { if ( ! pInstance ) // 1 { pInstance = new simpleSingleton ( ) ; // 2 } return pInstance ; // 3 }

At the very first access a thread call getInstance() and pInstance is null. The thread reaches the second line (2) and is ready to invoke the new operator. It might just happen that the OS scheduler unwittingly interrupts the first thread at this point and passes control to the other thread.

That thread follows the same steps: calls the new operator, assigns pInstance in place, and gets away with it.

After that the first thread resumes, it continues the execution of line 2, so it reassigns pInstance and gets away with it, too.

So now we have two singleton objects instead of one, and one of them will leak for sure. Each thread holds a distinct instance.

An improvement to this situation might be a thread locking mechanism and we have it in the new C++ standard C++ 11. So we don’t need using POSIX or OS threading stuff and now locking getInstance() from Meyers’s implementation looks like:

static otherSingleton& getInstance() { std::lock_guard lock(_mutex); static otherSingleton theInstance; pInstance = &theInstance; return *pInstance; } 1 2 3 4 5 6 7 8 9 static otherSingleton & getInstance ( ) { std :: lock_guard lock ( _mutex ) ; static otherSingleton theInstance ; pInstance = &theInstance ; return * pInstance ; }

The constructor of class std::lock_guard (C++11) locks the mutex, and its destructor unlocks the mutex. While _mutex is locked, other threads that try to lock the same mutex are blocked.

But in this implementation we’re paying for synchronization overhead for each getInstance() call and this is not what we need. Each access of the singleton requires the acquisition of a lock, but in reality we need a lock only when initializing pInstance. If pInstance is called n times during the course of a program run, we need the lock only for the first time.

Writing a C++ singleton 100% thread safe implementation it’s not as simple as it appears as long as for many years C++ had no threading standard support. In order to implement a thread-safe singleton we have to apply the double-checked locking (DCLP) pattern.

The pattern consists of checking before entering the synchronized code, and then check the condition again.

So the first singleton implementation would be rewritten using a temporary object:

static simpleSingleton* getInstance() { if (!pInstance) { std::lock_guard lock(_mutex); if (!pInstance) { simpleSingleton * temp = new simpleSingleton; pInstance = temp; } } return pInstance; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 static simpleSingleton * getInstance ( ) { if ( ! pInstance ) { std :: lock_guard lock ( _mutex ) ; if ( ! pInstance ) { simpleSingleton * temp = new simpleSingleton ; pInstance = temp ; } } return pInstance ; }

This pattern involves testing pInstance for nullness before trying to acquire a lock and only if the test succeeds the lock is acquired and after that, the test is performed again. The second test is needed for avoiding race conditions in case other thread happens to initialize pInstance between the time pInstance was tested and the time the lock was acquired.

Theoretically, this pattern is correct, but in practice is not always true, especially in multiprocessor environments.

Due to this rearranging of writes, the memory as seen by one processor at a time might look as if the operations are not performed in the correct order by another processor. In our case, the assignment to pInstance performed by a processor might occur before the Singleton object has been fully initialized.

After the first call of getInstance() the implementation with pointers (non-smart) needs pointer to that instance in order to avoid memory leaks.

Version 3 – Singleton with smart pointers

Until C++ 11, the C++ standard didn’t have a threading model and developers needed to use external threading APIs (POSIX or OS dependent primitives). But finally C++ 11 standard has threading support.

Unfortunately, the first C++ new standard implementation in Visual C++ 2010 is incomplete and threading support is available only starting with beta version of VS 2011 or the VS 2012 release preview version.

class smartSingleton { private: static std::mutex _mutex; smartSingleton(); smartSingleton(const smartSingleton& rs); smartSingleton& operator = (const smartSingleton& rs); public: ~smartSingleton(); static std::shared_ptr& getInstance() { static std::shared_ptr instance = nullptr; if (!instance) { std::lock_guard lock(_mutex); if (!instance) { instance.reset(new smartSingleton()); } } return instance; } void demo() { std::cout << "smart pointers # next - your code ..." << std::endl; } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class smartSingleton { private : static std :: mutex _mutex ; smartSingleton ( ) ; smartSingleton ( const smartSingleton & rs ) ; smartSingleton & operator = ( const smartSingleton & rs ) ; public : ~ smartSingleton ( ) ; static std :: shared_ptr & getInstance ( ) { static std :: shared_ptr instance = nullptr ; if ( ! instance ) { std :: lock_guard lock ( _mutex ) ; if ( ! instance ) { instance . reset ( new smartSingleton ( ) ) ; } } return instance ; } void demo ( ) { std :: cout << "smart pointers # next - your code ..." << std :: endl ; } } ;

As we know, in C++ by default the class members are private. So, our default constructor is private too. I added here in order to avoid misunderstanding and explicitly adding to public / protected.

Finally, feel free to use your special instance (singleton):

// Version 1 std::shared_ptr<smartSingleton> p = smartSingleton::getInstance(); // cache instance pointer p->demo(); // Version 2 std::weak_ptr<smartSingleton> pw = smartSingleton::getInstance(); // cache instance pointer pw.lock()->demo(); // Version 3 smartSingleton::getInstance()->demo(); 1 2 3 4 5 6 7 8 9 10 // Version 1 std :: shared_ptr < smartSingleton > p = smartSingleton :: getInstance ( ) ; // cache instance pointer p -> demo ( ) ; // Version 2 std :: weak_ptr < smartSingleton > pw = smartSingleton :: getInstance ( ) ; // cache instance pointer pw . lock ( ) -> demo ( ) ; // Version 3 smartSingleton :: getInstance ( ) -> demo ( ) ;

And no memory leaks emotion… 🙂

Multiple threads can simultaneously read and write different std::shared_ptr objects, even when the objects are copies that share ownership.

But even this implementation using double checking pattern but is not optimal to double check each time.



Version 4 – Thread safe singleton C++ 11

To have a thread safe implementation we need to make sure that the class single instance is locked and created only once in a multi-threaded environment.

Fortunately, C++ 11 comes in our help with two new entities: std::call_once and std::once_flag. Using them with a standard compiler we have the guaranty that our singleton is thread safely and no memory leak.

Invocations of std::call_once on the same std::once_flag object are serialized.

Instances of std::once_flag are used with std::call_once to ensure that a particular function is called exactly once, even if multiple threads invoke the call concurrently.

Instances of std::once_flag are neither CopyConstructible, CopyAssignable, MoveConstructible nor MoveAssignable.

Here it is my proposal for a singleton thread safe implementation in C++ 11:

class safeSingleton { static std::shared_ptr<safeSingleton> instance_; static std::once_flag only_one; safeSingleton(int id) { std::cout << "safeSingleton::Singleton()" << id << std::endl; } safeSingleton(const safeSingleton& rs) { instance_ = rs.instance_; } safeSingleton& operator = (const safeSingleton& rs) { if (this != &rs) { instance_ = rs.instance_; } return *this; } public: ~safeSingleton() { std::cout << "Singleton::~Singleton" << std::endl; } static safeSingleton & getInstance( int id ) { std::call_once( safeSingleton::only_one, [] (int idx) { safeSingleton::instance_.reset( new safeSingleton(idx) ); std::cout << "safeSingleton::create_singleton_() | thread id " + idx << std::endl; }, id ); return *safeSingleton::instance_; } void demo(int id) { std::cout << "demo stuff from thread id " << id << std::endl; } }; std::once_flag safeSingleton::only_one; std::shared_ptr <safeSingleton> safeSingleton::instance_ = nullptr; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class safeSingleton { static std :: shared_ptr < safeSingleton > instance_ ; static std :: once_flag only_one ; safeSingleton ( int id ) { std :: cout << "safeSingleton::Singleton()" << id << std :: endl ; } safeSingleton ( const safeSingleton & rs ) { instance_ = rs . instance_ ; } safeSingleton & operator = ( const safeSingleton & rs ) { if ( this != &rs ) { instance_ = rs . instance_ ; } return * this ; } public : ~ safeSingleton ( ) { std :: cout << "Singleton::~Singleton" << std :: endl ; } static safeSingleton & getInstance ( int id ) { std :: call_once ( safeSingleton :: only_one , [ ] ( int idx ) { safeSingleton :: instance_ . reset ( new safeSingleton ( idx ) ) ; std :: cout << "safeSingleton::create_singleton_() | thread id " + idx << std :: endl ; } , id ) ; return * safeSingleton :: instance_ ; } void demo ( int id ) { std :: cout << "demo stuff from thread id " << id << std :: endl ; } } ; std :: once_flag safeSingleton :: only_one ; std :: shared_ptr < safeSingleton > safeSingleton :: instance_ = nullptr ;

The parameter to getInstance() was added for demo reasons only and should be passed to a new proper constructor. As you can see, I am using a lambda instead normal method.

This is how I tested my safeSingleton and smartSingleton classes.

std::vector v; int num = 20; for( int n = 0; n < num; ++n ) { v.push_back( std::thread( []( int id ) { safeSingleton::getInstance( id ).demo( id ); }, n ) ); } std::for_each( v.begin(), v.end(), std::mem_fn( &std::thread::join ) ); // Version 1 std::shared_ptr<smartSingleton> p = smartSingleton::getInstance(1); // cache instance pointer p->demo("demo 1"); // Version 2 std::weak_ptr<smartSingleton> pw = smartSingleton::getInstance(2); // cache instance pointer pw.lock()->demo(2); // Version 3 smartSingleton::getInstance(3)->demo(3); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 std :: vector v ; int num = 20 ; for ( int n = 0 ; n < num ; ++ n ) { v . push_back ( std :: thread ( [ ] ( int id ) { safeSingleton :: getInstance ( id ) . demo ( id ) ; } , n ) ) ; } std :: for_each ( v . begin ( ) , v . end ( ) , std :: mem_fn ( &std :: thread :: join ) ) ; // Version 1 std :: shared_ptr < smartSingleton > p = smartSingleton :: getInstance ( 1 ) ; // cache instance pointer p->demo("demo 1"); // Version 2 std :: weak_ptr < smartSingleton > pw = smartSingleton :: getInstance ( 2 ) ; // cache instance pointer pw . lock ( ) -> demo ( 2 ) ; // Version 3 smartSingleton :: getInstance ( 3 ) -> demo ( 3 ) ;

So I create 20 threads and I launch them in parallel (std::thread::join) and each thread accesses getInstance() (with a demo id parameter). Only one of the threads that is trying to create the instance succeeds.

Additionally, if you’re using a C++11 100% compiler you could also delete the copy constructor and assignment operator. This will allow you to obtain an error while trying to use such deleted members.

Other comments

I tested this implementation on a machine with Intel i5 processor (4 cores). If you see some concurrent issues in this implementation please fell free to share here. I am open to other good implementations, too.

An alternative to this approach is creating the singleton instance of a class in the main thread and pass it to the objects which require it. In case we have many singleton objects this approach is not so nice because the objects discrepancies can be bundled into a single ‘Context’ object which is then passed around where necessary.

Update: According to Boris’s observation I removed std::mutex instance from safeSingleton class. This is not necessary anymore because std::call_once is enough to have thread safe behavior for this class.

Update2: According to Ervin and Remus’s observation, in order to make things clear I simplified the implementation version 3 and this is not using std::weak_ptr anymore.

References:

just::thread – Anthony Williams – Just Software Solutions Ltd

C++ and the Perils of Double-Checked Locking by Scott Meyers and Andrei Alexandrescu

Modern C++ Design: Generic Programming and Design Patterns Applied by Andrei Alexandrescu ( Romanian like me 🙂 )