Announcement

Tuesday, June 22, 2004

Implementing a Well behaved Singleton - 2

In the second part of this series, Lets look at a simple singleton implementation and see how these questions affect the implementation.

class FooSingleton
{
   public :
       FooSingleton(void);
       ~FooSingleton(void);

       static FooSingleton* GetFooObj(void);

   private :
      int m_var;

};


static FooSingleton g_fooSingleton;

FooSingleton*
FooSingleton::GetFooObj(void)
{
    return(&g_fooSingleton);
}
The problems with this code
(a) There is no guarantee that User of the class cannot create another instance of the class. So technically this is not a singleton.
(b) User can derive from this class. Usually not a good idea for singletons.
(c) Single instance is implemented using file static object. The sequence of static objects is decided by the compiler. Hence if other static objects depend on Singleton instance of FooSingleton, you have a problem. It may happen that g_fooSingleton is not initialzed yet.

Not a well behaved implementation.

Lets see how to improve on this. First lets make the constructor of the FooSingleton private. This will take care of (a) and (b). Problem however is then you cannot create file static 'g_fooSingleton'. It has to be implemented differently.

class FooSingleton
{
   public:
       ~FooSingleton(void);

       static FooSingleton* GetFooObj(void);

   private :
       FooSingleton(void);

   private :
      int m_var;
      static FooSingleton* m_pFoo;

};


FooSingleton* FooSingleton::m_pFoo= NULL;


FooSingleton*
FooSingleton::GetFooObj(void)
{
    if( m_pFoo == NULL)
           m_pFoo = new FooSingleton();

    return(m_pFoo);
}
First call to GetFooObj will create the Singleton instance, subsequence calls will return the same instance. There are still problems with this implementation.
1. GetFooObj is returning a pointer. What happens if user deletes this pointer by mistake ? The FooSinglton object will NOT know that the pointer is already deleted.
2. Exactly this singleton instance of FooSingleton is going to be destroyed ? Since m_pFoo is a pointer, its destructor will not get called automatically. That could be a problem.

The User (developer) has to manange the destruction of Singleton object and he needs to be really careful in using the class (.e.g don't keep copy of the pointer to FooSingleton, don't delete the pointer to FooSingleton etc). Not a well behaved implementation.

How to improve on this is part of next installment of this series :-)

No comments: