1

I'm trying to create a multi threaded and templated singleton as part of my advance c++ study. I've been told I have a race condition in my code and after hours of trying to figure it out i can't find it.

I won't write the whole class (though it's a simple one) but the exact location where I've been focused down to:

template <class T>
void Singleton<T>::onceFunction()
{
    static T instanceObject; 
    Singleton<T>::instance = &instanceObject;
}

template <class T>
T& Singleton<T>::getInstance()
{
    while (0 == Singleton::instance)
    {
        static pthread_once_t  once_control = PTHREAD_ONCE_INIT;
        pthread_once(&once_control, Singleton<T>::onceFunction);  
    }
    return *Singleton::instance;
}

I'm using pthread_once() since I'm not compiling with c++11.

  • You might find this useful: [stackoverflow](http://stackoverflow.com/questions/1962880/is-c-static-member-variable-initialization-thread-safe) – Paul Bentley May 04 '17 at 09:42
  • When is `once_control` initialized -- and on which thread? – G.M. May 04 '17 at 10:00

1 Answers1

1

The code you show is designed to protect/serialize the initailization of

static T instanceObject;

as defined in Singleton<T>::onceFunction(). In order to achieve that you use pthread_once. However, you have declared the pthread_once_t flag once_control at function/block scope with static storage...

static pthread_once_t  once_control = PTHREAD_ONCE_INIT;

Hence, I think the initialization of once_control suffers from the same race condition that your code is designed to solve for instanceObject.

Make once_control a static member of Singleton<T> instead.

Note: Your code also assumes the assignment...

Singleton<T>::instance = &instanceObject;

is atomic.

G.M.
  • 12,232
  • 2
  • 15
  • 18