views:

758

answers:

3

Hi all:

I am writing a library of utility classes, many of which are singletons. I have implemented them as such using inheritance:

template <class T>
class Singleton {
    public:
        T& getInstance() {
            if(m_instance == 0) {
                 m_instance = new T;
            }

            return m_instance;
        }
    private:
        static T* m_instance;
};

class SomeClass : public Singleton<SomeClass> {
    public:
        SomeClass() {}
        virtual ~SomeClass() {}

        void doSomething() {;}
};

Obviously this is a simple example, not an actual class. Anyways, I am finding that using code such as:

SomeClass::getInstance().doSomething();

Will create more than one instance of SomeClass. I am thinking this may be due to the fact that it is being used outside my library (.a) file as well as internally. For example, I am using a UI library not written by myself which is separately compiled and to which I am making additions. Some of these additions utilize singletons which are also being used in my .a library.

Is the separate compilation causing this? Something else?

The only way I have managed to get around the issue is to create a global object in my main.cpp file which I initialize with any singletons I will need. Then all code accesses this common global object with calls such as:

GlobalObject::getSomeClass().doSomething()

I hate having to add an additional method to this object every time I create another singleton. Plus the syntax seems clearer and more familiar using the first access method:

SomeClass::getInstance().doSomething();

Please let me know if you have any thoughts, opinions, etc.

Thanks.

+1  A: 

Are multiple threads accessing getInstance at the same time? That could cause multiple instances to be created. Consider:

  1. Thread 1 executes the "if (m_instance==0)" and finds it true
  2. Thread 2 executes the "if (m_instance==0)" and finds it true
  3. Thread 1 allocates a new T
  4. Thread 2 allocates a new T

Then one of them overwrites the other, and returns either one of the instances or the other (depending on compiler optimizations, etc.)

John Saunders
+1  A: 

Every template class you create from Singleton is going to have it's own static m_instance member... those are not shared across the different classes because when the templates are instantiated, it actually generates different classes for each set of template parameters. Judging by the way you're doing your inheritance, this probably means that you'll end up with an instance of Singleton for every one of the classes that derive from it. Perhaps this is the cause of your issue?

rmeador
+4  A: 

Your problem is that your template is going to be instantiated in more than one compilation unit as it is completely inline. Therefore in every compilation unit that uses the template you will end up creating one singleton (per compilation unit). What you would need is to force global linkage, so that all compilation units reference the same template instantiation. The upcoming C++ standard will support this via extern template. What you can do now is to disable automatic instantiation in your project and manually instantiate the templates that you use explicitly. This way when you use the template in any compilation unit you will generate an unknown reference to the implementation which can then be satisfied by the linker from the (one) compilation unit where you do the explicit instantiation.

lothar