Lock free Singleton class:

By the definition of Gang of four design pattern goes…
The singleton pattern is a design pattern that is used to ensure that a class can only
have one concurrent instance. Whenever additional objects of a singleton class are
required, the previously created, single instance is provided

Class diagram – sourced from Gang of Four.

Designing a singleton class from creational patterns category particularly ‘The lazy
initialization type’ and that is thread-safe comes with its own race-condition challenges,
hence programmers must ensure while designing such a class that it does not lead to a race
condition inside the method that provides a handle to the singleton instance requested for.

Since business of such a function by default come with critical section, we go for the
traditional synchronization locking mechanism that is a ‘mutex’ and call its lock/un-lock
functions around the critical section scope of the code.

Here, in this discussion we would be discussing with an example code to achieve the same
in a lock-free manner, that is we never use ‘mutex’ synchronization locking mechanism,
rather the best modern C++11,14 ,17 language & library features to achieve the same.

Some of the modern C++ language features employed in the example to be discussed…

  • Lambda expressions (C++11/14)
  • Delete methods (C++11)
  • Inline variables
  • Init-if

Modern C++ library features like…

  • Thread class library
  • Call_once function and once_flag
  • Shared_ptr from memory management library
#include<iostream>
#include<thread>
#include<mutex>
#include<memory>
using namespace std;
//C++14 approach - A LOCK-FREE singleton
once_flag Flag;
class Singleton
{
private:
    inline static shared_ptr<Singleton> ptr;
    Singleton();
   
public:
    Singleton(const Singleton &) = delete;
    Singleton(Singleton &&) = delete;
    Singleton& operator=(const Singleton &) = delete;
    Singleton& operator=(Singleton &&) = delete;
    static auto GetInstance();
    void Destroy();
    ~Singleton();
};
//All definitions
Singleton::Singleton()
{
cout <<"Singleton Constructor, :" << this_thread::get_id() <<endl;
}
auto Singleton::GetInstance()
    {
        //---lambda definition begins....
        auto Single_Instance = []()
        {
            if (auto* p= new(nothrow) Singleton(); p)
            {
                shared_ptr<Singleton> pt(p);
                ptr.swap(pt);
            }
            else
            {
                ptr = nullptr;
            }

            return ptr;
        };
        //---lambda definition ends...
        call_once(Flag, Single_Instance);  //Invoke the lambda
        return ptr;
    }
void Singleton::Destroy(){if(ptr) ptr.reset();}

Singleton::~Singleton()
{
    cout << "Singleton destructor..." << this_thread::get_id() <<endl;
}
//******************
void client1()
{
    auto tm = Singleton::GetInstance();
    if(tm)
        cout << "Singleton_handle : " << tm.get() << endl;
}
void client2()
{
    auto tm = Singleton::GetInstance();
    if(tm)
        cout << "Singleton_handle : " << tm.get() << endl;
}
int main()
{
    auto tm = Singleton::GetInstance();
    if(tm)
        cout << "Singleton_handle : " << tm.get() << endl;
    thread th1(client1);
    thread th2(client2);
   
    th1.join();
    th2.join();
    return 0;
}

The above example if you note when test would be thread-safe lock-free singleton.

Why Singleton design pattern?

Why Singleton design pattern?

There are number scenario’s where we need to ensure in a system, there shall only a single
instance of a particular type, allowing multiple instances would not really help the cause or
make any sense. For e.g.

A database Engine

Network print spooler

An XY or XYZ axis plane of a graph plot, no matter how many line graph
instances it may contain.