Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

singleton behaviour related query

I know this is very silly question about singleton pattern but still it is first choice of interviewer. Could you let me know in below code snippet.

(1) After deleting singleton object why still I am able to call show() method and it works fine.

delete obj;
obj=NULL;
obj->show();

(2) After creating obj1 object why i am not able to print the content of acquire_lock and release_lock function even print statment "one Time" will be printed once and if we increment counter i then instead of 2 it is printing 1 only, why?

Foo *obj1=MySingleton<Foo>::GetInstance();

(3) usage of unique_ptr with singleton object will have any negative implications.

code snippet:

#include <iostream>
#include <fstream>
#include <memory>
#include <string>

using namespace std;

static int i;

class Lock
{
public:
    Lock(){};
    ~Lock(){};

    void acquire_lock()
    {
        cout<<"aquired lock for class";
    }

    void release_lock()
    {
        cout<<"released lock for class";
    }

};

class Foo
{
public:
    void show()
    {
        cout<<"\ndone\n"; 
    }
};

template <class T>
class MySingleton
{
protected:

    MySingleton() {}

private:

    //holds one and only object of MySingleton
    static T* m_pOnlyOneInstance;
    MySingleton(const MySingleton <T> &) {};
    MySingleton <T> & operator=(const MySingleton <T> &) {};
    ~MySingleton() {};

public:

    static T * GetInstance();

    void foo()
    {
        cout<<"Mohan";
    }
};


template <class T>
T*  MySingleton<T>::GetInstance()
{
    Lock lock;
    if (m_pOnlyOneInstance == NULL)
    {  
        lock.acquire_lock();
        cout<<"one Time"<<endl;  
        i++; 
        if(m_pOnlyOneInstance == NULL)
        {
            m_pOnlyOneInstance = new T();
        }
        lock.release_lock();
    }  
    return m_pOnlyOneInstance;
}

template <class T> T* MySingleton<T> :: m_pOnlyOneInstance=NULL;

int main()
{
    //std::unique_ptr <Foo> obj (MySingleton<Foo>::GetInstance());
    Foo *obj=MySingleton<Foo>::GetInstance();    
    //obj->show();
    delete obj;
    obj=NULL;
    obj->show();
    cout<<"\ncalling again\n";
    Foo *obj1=MySingleton<Foo>::GetInstance();
    obj1->show();
    cout<<"i="<<i;  
    return 1;   
}

Note: lock related function are dummy implementation only.

like image 628
user3522354 Avatar asked Oct 19 '22 07:10

user3522354


1 Answers

  1. Keep in mind that obj->show() is equivalent to Foo::show(obj). Both expressions set this to the value of obj within the show member function. Now, what would setting this to NULL within show do? Nothing, because you never reference this.
  2. Well, think about the whole reason you would use the singleton pattern in the first place -- to initialize something at most one time. That "one time" print statement is in the code where the object gets instantiated, so naturally it doesn't get executed after the first time. Look at the logic of GetInstance. If an instance does not exist, it instantiates the class (messily... but it does work), and afterwards the instance exists. Otherwise, it does nothing.
  3. This question is very unclear, but what I assume you mean is "what are the negative implications of doing std::unique_ptr<Foo> obj = MySingleton<Foo>::GetInstance();?" As you can see from the reference for unique_ptr, its purpose is to take ownership of a dynamically allocated resource. This is definitely not supposed to happen when you're dealing with singleton objects. Because the resource (the singleton instance, in this case) is shared among any number of callers, the singleton class is the only one which should be managing the instance resource -- this is a fundamental invariant of the singleton pattern. If you use unique_ptr, as soon as obj goes out of scope, it will delete the instance automatically, regardless of whether your program references the now-freed instance elsewhere.
like image 141
mooiamaduck Avatar answered Nov 15 '22 10:11

mooiamaduck