DigestCPP

Lets Understand With Example

  • Home
  • Design Principal
  • Design Patterns
  • C++ 11 Features
  • C++11 Multithreading
  • Contact Us

Singleton Design Pattern C++

Singleton is most used Design pattern in the software industry and also most asked Design Pattern in interview so need to know.

C++ Singleton Design Pattern :

Definition:

It Ensures a class has ONE instance and provide a global access to it.

Class Diagram:

In layman language:

Class will create ONLY one instance and if we get request for another object then same object will be returned. We need to provide global access (it should be accessed from outside world).

Example:

  • Logger (we need to print the logs of all thread so that we need one object to do this job)
  • Configuration class (we need to set the configuration concurrency, it will be used by multiple threads so we need one object)

When will we use Singleton Design pattern:

In many scenario we have a requirement that class must create a single object.

Why will we use Singleton Design pattern:

Because singleton gives the guarantee that single object will be created by class and it will be accessed globally.

Methods to implement:

  • call once
  • static object
  • old method (double check thread safe method)

call once: This is new feature in C++11, without mutex we can create the one object with thread safe.

SingletonLogger *SingletonLogger::GetInstance()
{
    static std::once_flag oc;
    static SingletonLogger* m_pinstance;
    std::call_once(oc, []{ 
    static SingletonLogger obj;
    m_pinstance = &obj;
    std::cout<<"Object Address:"<<&m_pinstance<<std::endl;
    });
    return m_pinstance;
}

static object: We all know that static object is stored in data segment memory and persist in function calls and it will be live till the end of program so we can create a static object.

SingletonLogger *SingletonLogger::GetInstance()
{
    static SingletonLogger m_pinstance;
    return &m_pinstance;
}

old method (double check thread safe method): we will use two check condition with one mutex lock.

SingletonLogger *SingletonLogger::GetInstance()
{
    if (m_pinstance == nullptr)
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        if (m_pinstance == nullptr)
        {
            m_pinstance = new SingletonLogger();
        }
    }
    return m_pinstance;
}

source code with c++11:

/*
* File:singletonLogger.cpp
* This file is described the Singleton Design Pattern with help of example
* Singleton Design pattern:Ensure ONLY one object will be created.
* Singleton Design pattern:Provide Globall access to it.
* Author: Alpha Master
* Date: 18 April 2021
*/


///////////////////////////////////Header files////////////////////////////////////
#include <iostream>
#include <mutex>
#include <thread>  

//////////////////////////////////Singleton Start//////////////////////////////////////

class SingletonLogger
{

    private:
        std::mutex m_mutex;   
        //Singleton's constructor should be private to prevent creation of direct object.
        SingletonLogger(){}
        ~SingletonLogger() {}

        SingletonLogger(const SingletonLogger &other) = delete;  // Disallow copying
        void operator=(const SingletonLogger &) = delete;        // Disallow copying

    public:

        static SingletonLogger *GetInstance();
        void Print(const std::string str);
    
};

SingletonLogger *SingletonLogger::GetInstance()
{
    static std::once_flag oc;
    static SingletonLogger* m_pinstance;
    std::call_once(oc, []{ 
    static SingletonLogger obj;
    m_pinstance = &obj;
    std::cout<<"Object Address:"<<&m_pinstance<<std::endl;
    });
    return m_pinstance;
}

//Print Function of Logger, this is basic function to explain the use of singleton Pattern
// we can add according to our requirement.
void SingletonLogger::Print(const std::string str)
{
   std::lock_guard<std::mutex> lock(m_mutex);
   std::cout<<" value:"<<str<<std::endl;
}

///////////////////////////////////////////////Singleton END////////////////////////////////

void ThreadOne(){
    // Thread One
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    SingletonLogger::GetInstance()->Print("Thread ONE is executing");
}

void ThreadTwo(){
    // Thread Two
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    SingletonLogger::GetInstance()->Print("Thread TWO is executing");
}

int main()
{   
    std::thread t1(ThreadOne);
    std::thread t2(ThreadTwo);
    //waiting
    SingletonLogger::GetInstance()->Print("Parent process is Waiting for threads");    
    t1.join();
    t2.join();
    SingletonLogger::GetInstance()->Print("Check that address should be printed only once");
    SingletonLogger::GetInstance()->Print("Parent process saying BYE BYE");
    return 0;
}

Output:

Object Address:0x604328
 value:Parent process is Waiting for threads
 value:Thread TWO is executing
 value:Thread ONE is executing
 value:Check that address should be printed only once
 value:Parent process saying BYE BYE

Click Here to See source Code c++ Example

Primary Sidebar




DigestCPP © 2023. All rights reserved.

    About Privacy Policy Terms and Conditions Contact Us Disclaimer