R@M3$H.NBlog

Singleton Pattern

26 January, 2013 - 10 min read

Singleton Pattern

Well, to begin with, Singleton is one of the most commonly used - as well as misused - design patterns. Why did I say misused? You will get the answer as you read on.

Singleton Pattern is usually used to restrict the instances of a class, that is the objects within the life cycle of the software program to one. But why do we need to use Singletons? We use them:

  • to coordinate actions across the system
  • to improve upon the efficiency of the system

    Care should be taken to identify the need & benefits of using a singleton. Often, we tend to use singletons to hide a global object.

    How to Create a Singleton?

    Most of us know how to create a singleton. We have done it so many times by now, isn't it? But let us just do a quick recap.

    The thumb rule for singletons is that the direct instantiation through the constructor should be prevented. Then how do we instantiate or access the object? The solution is to provide a method that creates a new instance of the object if one does not exist. If an instance already exists, it simply returns a reference to that object.

    class
    Singleton {

        Singleton() {

        }

    };

    Remember the default access in a C++ class is private.

    Now that we have prevented the direct instantiation of the class, we need to provide a mechanism to access the object. Here is how we do this:

    class
    Singleton {

    public:

        static
    Singleton* getInstance() {

            if (NULL == _instance) {

                _instance = new
    Singleton();

            }

            return _instance;

        }

    private:

        // default constructor

        Singleton() {

        }

        // the single instance of the object

        static
    Singleton* _instance;

    };

    Singleton* Singleton::_instance = NULL;

    Now we have ensured that only one instance exists and gives access to the same. Now other required functionality can be added to the Singleton class.

    Is That All?

    Are we done? No, not quite exactly. Remember I had said that this is an attempt to create a perfect Singleton. So what is wrong with the above? Have we missed something? Yes, we did. Though we have prevented the direct instantiation, an object can still be created. If you recollect the basics, all C++ classes, apart from having their default constructors also have:

  • copy constructor
  • assignment operator

    We need to declare these also as private so as to prevent the access. You may ask why. We do so because:

  • a copy constructor will create a new object from the existing one. But we are interested in limiting the instance to only one.
  • an assignment operator is not required for a Singleton; '_instance' is the only data member & has to point to the same object across all instances.

    class
    Singleton {

    public:

        static
    Singleton* getInstance() {

            if (NULL == _instance) {

                _instance = new
    Singleton();

            }

            return _instance;

        }

    private:

        // default constructor

        Singleton() {

        }

        // copy constructor

        Singleton(const
    Singleton&) {

        }

        // assignment operator

        Singleton& operator=(const
    Singleton&) {

            return *this;

        }

        // the single instance of the object

        static
    Singleton* _instance;

    };

    Singleton* Singleton::_instance = NULL;

    How Do We Release the Singleton?

    Now we have prevented alternatives to create another instance of the class. But what about the destruction of the instance? Can we define a destructor & delete _instance in it? This though looks very simple enough, it isn't. If you do the above, you will have your code as:

    class
    Singleton {

    public:

    . . .

    . . .

        ~Singleton() {

            delete _instance;

        }

    };

    What actually happens in that destructor, is that delete _instance invokes the destructor again & puts it into an infinite loop. So the easy way out seems to be to depend on the post program termination clean-up to release the memory. But then it is not a good practice to depend on the post program termination clean up for the new that we had done. Hence I recommend to have a releaseInstance() and to prevent access to the default destructor by making it private.


    class
    Singleton {

    public:

        static
    Singleton* getInstance() {

            if (NULL == _instance) {

                _instance = new
    Singleton();

            }

            return _instance;

        }

        static
    void releaseInstance() {

            if (NULL != _instance) {

                delete _instance;

                _instance = NULL;

            }

        }

    private:

        // default constructor

        Singleton() {

        }

        // default destructor

        ~Singleton() {

        }

        // copy constructor

        Singleton(const
    Singleton&) {

        }

        // assignment operator

        Singleton& operator=(const
    Singleton&) {

            return *this;

        }

        // the single instance of the object

        static
    Singleton* _instance;

    };

    Singleton* Singleton::_instance = NULL;

    Tune the Release of Singleton

    Now that looks perfect. All said & done, there still is a catch. When should releaseInstance() be called? Ideally, this should be called when the application exits. But in a real time situation when there are multiple developers working on the application code, it just remains a mirage. So what do we do? We will use a reference count to ensure that the actual destruction of the Singleton happens only when it is not being referenced anymore. So we add a static reference count to the Singleton.

    class
    Singleton {

    public:

        static
    Singleton* getInstance() {

            if (NULL == _instance) {

                _instance = new
    Singleton();

            }

            _referenceCount++;

            return _instance;

        }

        static
    void releaseInstance() {

            _referenceCount--;

            if ((0 == _referenceCount) && (NULL != _instance)) {

                delete _instance;

                _instance = NULL;

            }

        }

    private:

        // default constructor

        Singleton() {

        }

        // default destructor

        ~Singleton() {

        }

        // copy constructor

        Singleton(const
    Singleton&) {

        }

        // assignment operator

        Singleton& operator=(const
    Singleton&) {

            return *this;

        }

        // the single instance of the object

        static
    Singleton* _instance;

        // the count of references

        static
    int _referenceCount;

    };

    int
    Singleton::_referenceCount =
    0;

    Singleton* Singleton::_instance = NULL;

    This is much better, but still not completely foolproof. If the releaseInstance() is called more than required by one particular user, it will lead to a situation where an instance is deleted even though it is actually still very much in use. On the contrary, if the releaseInstance() is not called by a user, then the Singleton will never be deleted & we are back to depending on the post program termination clean up.

    In case of Java, as far as my knowledge goes, garbage collection takes care of releasing the instance when it is not referenced anymore. So not much problem as envisaged above for C++.

    Finale

    A simple way to handle the limitations in C++ is through effective code review. But the risk still remains as it is directly proportionate to the effectiveness of the code review. Though there is another workaround to minimize this risk, there always seems to be a way to hack through.

    Destruction:

    class
    Singleton {

    public:

    . . .

    . . .

        ~Singleton() {

            if ( _instance != NULL ) {

                Singleton* tmpPtr = _instance ;

                _instance = NULL ;

                delete tmpPtr ;

            }

        }

    };

    On the 2nd call to ~Singleton, _instance will be null, so it won't get stuck in the infinite loop. Then, you don't need the ReleaseInstance function