If you need an object which should present as one instance, then a singleton pattern can be the answer for you. But If you quickly search the internet, you can see some people say that the singleton pattern is an antipattern. I am not sure it is correct 100 percent, but it has some drawbacks.
We will see how we can create a singleton pattern with some examples in this post. Also, thread safety is discussed because, as I see, a singleton is a really dangerous pattern if you do not know what you are doing.
The main point of the singleton pattern is a static keyword. Static keyword allows you to create a variable that will be stored in the data segment(BSS) of the program memory (virtual memory) and act as a global variable. So that means it’s lifetime is equal to the binary of the lifetime.
But here, our intention is to create a class, and this class should be constructed once or should be created once; and if someone wants to create it again, it should return the previous address of the object to use the old content of the object.
To achieve this, we can make the constructor private, so no one can construct the object. But how can it be used, then? The constructor will be called from another public member function which returns the static instance of the object.
So first, let’s use stack-based design and see why it is NOT useful first.
#include <iostream> using namespace std; class Singleton { // Private constructor so that no objects can be created. Singleton() { } static Singleton instance; public: static Singleton& getInstance() { return instance; } }; Singleton Singleton::instance; int main(){ Singleton s = Singleton::getInstance(); std::cout<<&s<<std::endl; Singleton s2 = Singleton::getInstance(); std::cout<<&s2<<std::endl; return 0; }
As you see in the above code snippet, we have a static singleton instance; it is initialized outside of the class ( it is because of the static keyword usage ). It is a good idea to say that no one can create the object like Singleton s; or sth because of the private status of the constructor. And using getInstance() method, we would like to return the same object again and again. But it is working really? Let’s try to print the address of the objects that we get from the method.
0x7ffeaea5376f 0x7ffeaea5376e
As you see, they are not the same. This is not what we want. Why are they not the same? Because we did not disable the copy constructor and for each getInstance(), it tries to call copy constructor and create the new instance. Huh? Not nice. Let’s try to disable the copy constructor ( and assignment).
#include <iostream> using namespace std; class Singleton { // Private constructor so that no objects can be created. Singleton() { } static Singleton instance; public: Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static Singleton& getInstance() { return instance; } }; Singleton Singleton::instance; int main(){ Singleton s = Singleton::getInstance(); std::cout<<&s<<std::endl; Singleton s2 = Singleton::getInstance(); std::cout<<&s2<<std::endl; return 0; }
Now we have compilation error ? Why ?

Simply we want to disable the copy constructor, but the method itself pushes the class to use a copy constructor. So what should we do? We have pointers!
Now let’s not keep the object itself in the stack. We can create the static pointer to keep it in the BSS, and this pointer can point to the memory area in a heap. What a nice idea?
Here is the code for it.
#include <iostream> using namespace std; class Singleton { // Private constructor so that no objects can be created. Singleton() { } static Singleton *instance; public: Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static Singleton *getInstance() { if (!instance) instance = new Singleton; return instance; } }; Singleton *Singleton::instance = 0; int main(){ // Singleton *s = s->getInstance(); // we can use like this ? Singleton *s = Singleton::getInstance(); Singleton *s2 = Singleton::getInstance(); std::cout<<s<<std::endl; std::cout<<s2<<std::endl; return 0; }
Now we return the address of the object instead of itself. So as we know that when we use pointers like Singleton* s; this will not call the constructor. Because it is a pointer! ( size of the pointer can vary according to machine memory address size. For the 32-bit machine, pointer size is 4 bytes, and for the 64-byte machine, it is 8).
If you check the output of the code, then you will see the same address.
0xa60eb0 0xa60eb0
Now let us try to improve the code a little bit step by step. We have an instance definition outside of the class lets remove it and move all implementation in the getInstance() method.
#include <iostream> using namespace std; class Singleton { // Private constructor so that no objects can be created. Singleton() { } public: Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static Singleton *getInstance() { static Singleton *instance = new Singleton; return instance; } }; int main(){ // Singleton *s = s->getInstance(); // we can use like this ? Singleton *s = Singleton::getInstance(); Singleton *s2 = Singleton::getInstance(); std::cout<<s<<std::endl; std::cout<<s2<<std::endl; return 0; }
We can use the static definition in the function itself; static keyword makes our variable will be initialized only once, even if the function will be called more than one time. Nice and clean!
So you may ask yourself if accessing the getInstance method from different threads at the same time is thread-safe. You catch me! Well, the question is yes. It is totally thread-safe. Let me prove it with the valgrind tool.
To test this, let’s add two threads and make the main wait a little bit. What we want to call the getInstance method and pass the return pointer to the variable in the different threads.
#include <iostream> #include <thread> class Singleton { // Private constructor so that no objects can be created. Singleton() { } public: Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static Singleton *getInstance() { static Singleton *instance = new Singleton; return instance; } }; int main(){ // Singleton *s = s->getInstance(); // we can use like this ? Singleton *s = Singleton::getInstance(); std::thread([&](){ Singleton *s2 = Singleton::getInstance(); }).detach(); std::thread([&](){ Singleton *s3 = Singleton::getInstance(); }).detach(); std::this_thread::sleep_for (std::chrono::seconds(1)); return 0; }
If you compile the code using :
g++ singletonExample.cpp -std=c++14 -lpthread -o singleton
And run the valgrind to check race conditions:
valgrind --tool=helgrind ./singleton
Then you will see there is no problem from thread safety perspective.

But why is this thread safe? There is no protection. How can it be thread-safe? If you check here: https://timsong-cpp.github.io/cppwp/n4861/stmt.dcl
It says, “If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for the completion of the initialization.” So that means static is thread-safe!
Hmm, so can we use the static class without worrying about race conditions? ofcouse not. It depends on the situation.
What we have until now is simply one getInstance method which returns the static pointer and nothing more. Let’s add one integer to our class with set and get methods. I would like to name our integer X !
#include <iostream> #include <thread> class Singleton { // Private constructor so that no objects can be created. Singleton():X(0) { } public: int X; Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static Singleton *getInstance() { static Singleton *instance = new Singleton; return instance; } void setX(int x) { X = x; } int getX() { return X; } }; int main(){ // Singleton *s = s->getInstance(); // we can use like this ? Singleton *s = Singleton::getInstance(); s->setX(3); s->getX(); std::thread([&](){ Singleton *s2 = Singleton::getInstance(); s2->setX(5); s2->getX(); }).detach(); std::thread([&](){ Singleton *s3 = Singleton::getInstance(); s3->setX(6); s3->getX(); }).detach(); std::this_thread::sleep_for (std::chrono::seconds(2)); return 0; }
Simple we set and get the X from main thread and other two threads. Then If you run the valgrind, you will see the output like:
g++ singletonExample.cpp -std=c++14 -lpthread -o singleton valgrind --tool=helgrind ./singleton

Ta ta !!! We have an error. But why? Actually, it is obvious because no one protects the X variable from multiple access at the same time. So what I am trying to say is that getInstance can be thread-safe, but that does not mean it will make out other variables thread-safe. So what should we do? We can use atomic variables or we can just add one mutex around in the functions which are related to X. Lets make X atomic.
#include <iostream> #include <thread> #include <atomic> class Singleton { // Private constructor so that no objects can be created. Singleton():X(0) { } public: std::atomic<int> X; Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static Singleton *getInstance() { static Singleton *instance = new Singleton; return instance; } void setX(int x) { X.exchange(x); } int getX() { return X.load(); } }; int main(){ // Singleton *s = s->getInstance(); // we can use like this ? Singleton *s = Singleton::getInstance(); s->setX(3); s->getX(); std::thread([](){ Singleton *s2 = Singleton::getInstance(); s2->setX(5); s2->getX(); }).detach(); std::thread([](){ Singleton *s3 = Singleton::getInstance(); s3->setX(6); s3->getX(); }).detach(); std::this_thread::sleep_for (std::chrono::seconds(2)); return 0; }
As you see from the above code snippet, X is atomically used. If you run the Valgrind again, you will see no problem. Be careful here; if you change the X.exchange(x); with X.store(x); then you can see an issue with Valgrind (helgrind). If you want, you can try this with a mutex; you will see no problem. I do not want to spend more time here because I would like to jump into another problem 🙂

For next step lets check is there any leak or not. We can use the valgrind again.
Run the command:
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose ./singleton
Then in the output you will see that :

It says there is no error, but if you check the still reachable part and it is a problem. 4 Byte is still reachable. It is because we did not delete the singleton instance in a heap.
So if we add delete s; to the end of the main.
#include <iostream> #include <thread> #include <atomic> class Singleton { // Private constructor so that no objects can be created. Singleton():X(0) { } public: std::atomic<int> X; Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static Singleton *getInstance() { static Singleton *instance = new Singleton; return instance; } void setX(int x) { X.exchange(x); } int getX() { return X.load(); } }; int main(){ // Singleton *s = s->getInstance(); // we can use like this ? Singleton *s = Singleton::getInstance(); s->setX(3); s->getX(); std::thread([](){ Singleton *s2 = Singleton::getInstance(); s2->setX(5); s2->getX(); }).detach(); std::thread([](){ Singleton *s3 = Singleton::getInstance(); s3->setX(6); s3->getX(); }).detach(); std::this_thread::sleep_for (std::chrono::seconds(2)); delete s; return 0; }
Then in the valgrind:

Looks okay! Or is it not? Well, we clean the memory area at the end of the code. But how do we know it? This is a simple program. If the program is a little big, who will delete our precious singleton memory in a heap?
Until now, what we did is quite not enough. In this case, there can be many solutions. But I would like to introduce this design with ownership of the smart pointers. For instance with unique_ptr.
But if we want to use unique_ptr, we need to make the constructor public. This is what we do not want. So we have to do some tricks. We will pass the parameter from our constructor, and it will allow no one can create without the parameter. The constructor will be public, but the parameter which is passed will be private. And getInstance will return the object using the proper constructor(with parameter). There is a sleep at the end of the main, it is because of threads are detach, and there will be a chance to finish the program before threads finishe the execution. This can create possible lost in the memory that it is possible to see with valgrind. So if you want to remove sleep you can use .join() for threads instead of .detach().
Then we do not have to care about the ownership because unique_ptr will handle it for us.
#include <iostream> #include <memory> #include <thread> #include <mutex> class Singleton { private: static std::unique_ptr<Singleton> instance; struct _cons {explicit _cons() = default; }; std::mutex m; public: int X; Singleton(_cons){} static std::unique_ptr<Singleton> instanceFactory() { return std::make_unique<Singleton>(_cons{}); } static std::unique_ptr<Singleton>& getInstance(); void setX(int x) { std::lock_guard<std::mutex> guard(m); X = x; } int getX() { std::lock_guard<std::mutex> guard(m); return X; } }; std::unique_ptr<Singleton>& Singleton::getInstance() { /* If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. */ static std::unique_ptr<Singleton> instance { Singleton::instanceFactory() }; return instance; } int main() { //std::unique_ptr<Singleton> s = std::make_unique<Singleton>; //Error { std::unique_ptr<Singleton> &p = Singleton::getInstance(); } std::thread([&](){ std::unique_ptr<Singleton> &p2 = Singleton::getInstance(); p2->setX(1); int var = p2->getX(); }).detach(); std::thread([&](){ std::unique_ptr<Singleton> &p3 = Singleton::getInstance(); int var = p3->getX(); p3->setX(2); var = p3->getX(); }).detach(); std::this_thread::sleep_for (std::chrono::seconds(4)); return 0; }
If you run the valgrind for above code you will see no problem.


As you see getInstance method transfers the ownership of the object. This can be undesired. To overcome this issue we can pass raw pointer to hide the ownership.
#include <iostream> #include <memory> #include <thread> #include <mutex> class Singleton { private: static std::unique_ptr<Singleton> instance; struct _cons {explicit _cons() = default; }; std::mutex m; public: int X; Singleton(_cons){} static std::unique_ptr<Singleton> instanceFactory() { return std::make_unique<Singleton>(_cons{}); } static Singleton* getInstance() { /* If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. */ static std::unique_ptr<Singleton> instance { Singleton::instanceFactory() }; return instance.get(); } void setX(int x) { std::lock_guard<std::mutex> guard(m); X = x; } int getX() { std::lock_guard<std::mutex> guard(m); return X; } }; int main() { //Singleton* s = new Singleton(); //Error { Singleton* p = Singleton::getInstance(); } std::thread([&](){ Singleton* p2 = Singleton::getInstance(); p2->setX(1); int var = p2->getX(); }).detach(); std::thread([&](){ Singleton* p3 = Singleton::getInstance(); int var = p3->getX(); p3->setX(2); var = p3->getX(); }).detach(); std::this_thread::sleep_for (std::chrono::seconds(4)); return 0; }
Same pattern can be implemented with shared_ptr. In this case there will be small overhead because of reference counting.