[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

Confused about a thread-safe singleton example.

jason.cipriani@gmail.com

12/3/2008 12:25:00 AM

I have a C++-specific question about thread-safe singleton instances.
There's a trivial example here:

http://www.bombaydigital.com/arenared/20...

That goes like this, very simple and straightforward:

static Mutex mutex;
static TheClass *instance;

static TheClass * getInstance () {
MutexLocker lock(mutex);
if (!instance)
instance = new TheClass();
return instance;
}

The example then goes on to talk about how double-check locking is
broken, etc. My question is pretty much this: Is C++ static
initialization thread-safe? If not, then how does the above example
safely use "mutex"? If so, then what is wrong with this:

static TheClass instance; // not a pointer

static TheClass * getInstance () {
return &instance; // it's correctly initialized?
}

The reason I ask is I almost never see it done like that, I always see
blog entries and articles that say the same thing "store instance in a
pointer, use a mutex to protect, and p.s. double-checked locking is
broken". It seems like doing it lock-free is made out to be a hard
problem, so *if* having a static instance works (but I don't know if
it does, that's my question), then why doesn't anybody ever suggest
it?

Thanks!
Jason
64 Answers

Sam

12/3/2008 2:18:00 AM

0

jason.cipriani@gmail.com writes:

> static Mutex mutex;
> static TheClass *instance;
>
> static TheClass * getInstance () {
> MutexLocker lock(mutex);
> if (!instance)
> instance = new TheClass();
> return instance;
> }
>
> The example then goes on to talk about how double-check locking is
> broken, etc. My question is pretty much this: Is C++ static
> initialization thread-safe? If not, then how does the above example
> safely use "mutex"? If so, then what is wrong with this:
>
> static TheClass instance; // not a pointer
>
> static TheClass * getInstance () {
> return &instance; // it's correctly initialized?
> }
>
> The reason I ask is I almost never see it done like that, I always see
> blog entries and articles that say the same thing "store instance in a
> pointer, use a mutex to protect, and p.s. double-checked locking is
> broken". It seems like doing it lock-free is made out to be a hard
> problem, so *if* having a static instance works (but I don't know if
> it does, that's my question), then why doesn't anybody ever suggest
> it?

Setting aside the fact that there's no such thing as threads or mutexes in
the C++ language (at least not yet), so you are using a platform specific
library here.

Your statically declared instance gets constructed at some unspecified point
before your main() function gets invoked. If you have other objects in
static scope, it is unspecified the order in which all your static instances
get initialized. This may be undesirable. It's possible that it is necessary
to construct your singleton in a more controlled fashion, after all your
other objects, in static scope or otherwise, get initialized. Using a
dynamically-allocated pointer to your singleton, and protecting it with a
mutex, gives you the means to accomplish that.


jason.cipriani@gmail.com

12/3/2008 4:19:00 AM

0

On Dec 2, 9:17 pm, Sam <s...@email-scan.com> wrote:
> jason.cipri...@gmail.com writes:
> > static Mutex mutex;
> > static TheClass *instance;
>
> > static TheClass * getInstance () {
> >    MutexLocker lock(mutex);
> >    if (!instance)
> >      instance = new TheClass();
> >    return instance;
> > }
>
> > The example then goes on to talk about how double-check locking is
> > broken, etc. My question is pretty much this: Is C++ static
> > initialization thread-safe? If not, then how does the above example
> > safely use "mutex"? If so, then what is wrong with this:
>
> > static TheClass instance; // not a pointer
>
> > static TheClass * getInstance () {
> >   return &instance; // it's correctly initialized?
> > }
>
> > The reason I ask is I almost never see it done like that, I always see
> > blog entries and articles that say the same thing "store instance in a
> > pointer, use a mutex to protect, and p.s. double-checked locking is
> > broken". It seems like doing it lock-free is made out to be a hard
> > problem, so *if* having a static instance works (but I don't know if
> > it does, that's my question), then why doesn't anybody ever suggest
> > it?
>
> Setting aside the fact that there's no such thing as threads or mutexes in
> the C++ language (at least not yet), so you are using a platform specific
> library here.

I just used "Mutex" and "AutoMutex" as an example.

> Your statically declared instance gets constructed at some unspecified point
> before your main() function gets invoked. If you have other objects in
> static scope, it is unspecified the order in which all your static instances
> get initialized. This may be undesirable. It's possible that it is necessary
> to construct your singleton in a more controlled fashion, after all your
> other objects, in static scope or otherwise, get initialized. Using a
> dynamically-allocated pointer to your singleton, and protecting it with a
> mutex, gives you the means to accomplish that.

I see. So, it's safe to use a global-scoped static instance for the
singleton instance, as long as you don't need *precise* control over
when it's initialized (just as long as it's initialized before it's
used)? Even if it's accessed from different translation units (and
defined in a different one than main() is in)?

I did an experiment with VS 2008 where I made the singleton class's
constructor Sleep() for 2 seconds hoping to make a race condition
occur, and did this:

=== A.h ===
class A {
public:
A ();
~A ();
static A * getInstance ();
};

=== A.cpp ===
static A theInstance;
A * A::getInstance () { return &theInstance; }

I had main() in a different source file, and it created some threads
with functions in a 3rd source file. I called A::getInstance() in each
of those threads, and saw that theInstance was initialized before main
() was even entered, and everything worked great.

Is this standard behavior that I can rely on, or is it specific to the
MS compiler?

I also tried making theInstance function-scoped, in the getInstance()
function. That didn't work, I guess there's different rules for
function-scoped static initialization (I did read that, and also read C
++0x makes some guarantees about it). I noticed that if I created
multiple threads like this:

threadproc () {
A * a = A::getInstance();
}

The first thread created waited the 2 seconds as the A() was
constructed, but every thread after that immediately returned, *with*
the pointer, but before the A() constructor had returned.

A * A::getInstance () {
static A theInstance;
return &theInstance;
}

I guess that makes sense. "&theInstance" is already known, so threads
can return immediately while it's still being constructed.

The third thing I tried was storing theInstance at class scope, and
using a pointer but statically initializing it with new(). That also
worked, it was initialized before main() was entered. Is this also
behavior that can be relied on? E.g.:

class A {
static A * getInstance ();
...
static A * theInstance;
};

A * A::theInstance = new A();

A * A::getInstance () { return theInstance; }


So, global scope worked, class scope worked, function scope was all
messed up.


Thanks,
Jason

Alan Johnson

12/3/2008 6:47:00 AM

0

jason.cipriani@gmail.com wrote:
> I have a C++-specific question about thread-safe singleton instances.
> There's a trivial example here:
>
> http://www.bombaydigital.com/arenared/20...
>
> That goes like this, very simple and straightforward:
>
> static Mutex mutex; static TheClass *instance;
>
> static TheClass * getInstance () { MutexLocker lock(mutex); if
> (!instance) instance = new TheClass(); return instance; }
>
> The example then goes on to talk about how double-check locking is
> broken, etc. My question is pretty much this: Is C++ static
> initialization thread-safe? If not, then how does the above example
> safely use "mutex"? If so, then what is wrong with this:
>
> static TheClass instance; // not a pointer
>
> static TheClass * getInstance () { return &instance; // it's
> correctly initialized? }
>
> The reason I ask is I almost never see it done like that, I always
> see blog entries and articles that say the same thing "store instance
> in a pointer, use a mutex to protect, and p.s. double-checked locking
> is broken". It seems like doing it lock-free is made out to be a hard
> problem, so *if* having a static instance works (but I don't know if
> it does, that's my question), then why doesn't anybody ever suggest
> it?
>
> Thanks! Jason

1. Don't use singletons. Ever. Pretty much all of the value of the GoF
Design Patterns book is negated by the fact that they chose to
legitimize Singleton as a design pattern. Singleton is just a fancy
name for global variable. We should call it the Global Variable
(anti)Pattern.

2. If you think you've found a good reason to use a singleton, see point #1.

3. Double checked locking works without memory fencing on x86:
http://bartoszmilewski.wordpress.com/2008/11/05/who-ordered-memory-fences-...

Thus, your main opponent in the optimizer.

4. Whether or not the construction of a static variable is threadsafe
depends mostly on the implementation (the standard says nothing about
it). gcc has an option =fno-threadsafe-statics to turn off the extra
code emitted to make local statics thread safe. I guess one could
extrapolate that by default local statics are thread safe in gcc (though
I have no idea if this is actually true).


--
Alan Johnson

anon

12/3/2008 6:57:00 AM

0

jason.cipriani@gmail.com wrote:
> I have a C++-specific question about thread-safe singleton instances.
> There's a trivial example here:
>
> http://www.bombaydigital.com/arenared/20...
>
> That goes like this, very simple and straightforward:
>
> static Mutex mutex;
> static TheClass *instance;
>
> static TheClass * getInstance () {
> MutexLocker lock(mutex);
> if (!instance)
> instance = new TheClass();
> return instance;
> }

Where do you unlock the mutex?

>
> The example then goes on to talk about how double-check locking is
> broken, etc. My question is pretty much this: Is C++ static
> initialization thread-safe? If not, then how does the above example
> safely use "mutex"? If so, then what is wrong with this:
>
> static TheClass instance; // not a pointer
>
> static TheClass * getInstance () {
> return &instance; // it's correctly initialized?
> }

You do not have a compilable code, but if instance is global variable,
then it is initialized before entering main(). Therefore, before any
thread is created

btw in this case, the getInstance function can be like this:
static TheClass & getInstance () {
return instance; // it's correctly initialized?
}

>
> The reason I ask is I almost never see it done like that, I always see
> blog entries and articles that say the same thing "store instance in a
> pointer, use a mutex to protect, and p.s. double-checked locking is
> broken". It seems like doing it lock-free is made out to be a hard
> problem, so *if* having a static instance works (but I don't know if
> it does, that's my question), then why doesn't anybody ever suggest
> it?
>
> Thanks!
> Jason


I think your suggestion should be like this:

static TheClass * getInstance () {
MutexLocker lock(mutex);
return &instance; // it's correctly initialized?
}
because in the first function, there is a mutex locked, so only one
thread can access the class instance at the time



Sorry I didn't answer your question - I do not know the answer :(

Kai-Uwe Bux

12/3/2008 7:49:00 AM

0

anon wrote:

> jason.cipriani@gmail.com wrote:
>> I have a C++-specific question about thread-safe singleton instances.
>> There's a trivial example here:
>>
>> http://www.bombaydigital.com/arenared/20...
>>
>> That goes like this, very simple and straightforward:
>>
>> static Mutex mutex;
>> static TheClass *instance;
>>
>> static TheClass * getInstance () {
>> MutexLocker lock(mutex);
>> if (!instance)
>> instance = new TheClass();
>> return instance;
>> }
>
> Where do you unlock the mutex?
[snip]

Just a guess: in the destructor of MutexLocker.


Best

Kai-Uwe Bux

jason.cipriani@gmail.com

12/3/2008 8:02:00 AM

0

On Dec 3, 1:47 am, Alan Johnson <aw...@yahoo.com> wrote:
> jason.cipri...@gmail.com wrote:
> > I have a C++-specific question about thread-safe singleton instances.
> >  There's a trivial example here:
>
> >http://www.bombaydigital.com/arenared/20...
>
> > That goes like this, very simple and straightforward:
>
> > static Mutex mutex; static TheClass *instance;
>
> > static TheClass * getInstance () { MutexLocker lock(mutex); if
> > (!instance) instance = new TheClass(); return instance; }
>
> > The example then goes on to talk about how double-check locking is
> > broken, etc. My question is pretty much this: Is C++ static
> > initialization thread-safe? If not, then how does the above example
> > safely use "mutex"? If so, then what is wrong with this:
>
> > static TheClass instance; // not a pointer
>
> > static TheClass * getInstance () { return &instance; // it's
> > correctly initialized? }
>
> > The reason I ask is I almost never see it done like that, I always
> > see blog entries and articles that say the same thing "store instance
> > in a pointer, use a mutex to protect, and p.s. double-checked locking
> > is broken". It seems like doing it lock-free is made out to be a hard
> >  problem, so *if* having a static instance works (but I don't know if
> >  it does, that's my question), then why doesn't anybody ever suggest
> > it?
>
> > Thanks! Jason
>
> 1. Don't use singletons.  Ever.  Pretty much all of the value of the GoF
> Design Patterns book is negated by the fact that they chose to
> legitimize Singleton as a design pattern.  Singleton is just a fancy
> name for global variable.  We should call it the Global Variable
> (anti)Pattern.
>
> 2. If you think you've found a good reason to use a singleton, see point #1.

In this case, the object in question is used as a "default object"
when some other non-default object isn't explicitly used (sorry I'm
being vague, but there's not much need to explain it). Maintaining a
single instance of the "default object" eliminates the need to have to
clean up separate default object instances, and to keep track of
whether or not clean up is necessary, who owns the object, etc. It
greatly simplifies a lot of application code. And you are correct, in
this case it basically is, in fact, a global variable.

> 3. Double checked locking works without memory fencing on x86:http://bartoszmilewski.wordpress.com/2008/11/05/who-ordered......
>
> Thus, your main opponent in the optimizer.
>
> 4. Whether or not the construction of a static variable is threadsafe
> depends mostly on the implementation (the standard says nothing about
> it). gcc has an option =fno-threadsafe-statics to turn off the extra
> code emitted to make local statics thread safe.  I guess one could
> extrapolate that by default local statics are thread safe in gcc (though
> I have no idea if this is actually true).

I think you may be talking about function-local statics. C++
guarantees that global-scoped statics are initialized before main().
This means that, as long as the singleton class initialization doesn't
depend on objects being initialized in other translation units (and
the other way around), it *will* be properly initialized before main
(), and therefore it will be properly initialized before any threads
access it (assuming all threads are created after main starts, not
during static initialization). So no locking would be needed (on any
platforms); getInstance() would always return a completely initialized
object -- here is the method I finally settled on:

=== MyClass.h ===

class MyClass {
....
static MyClass * getInstance ();
....
};

=== MyClass.cpp ===

static MyClass *instance = new MyClass();

MyClass * MyClass::getInstance () {
return instance;
}

The same appears to be true for class-scoped statics as well, but I
didn't do any more digging because the above solved the problem.

Thanks,
Jason


>
> --
> Alan Johnson

anon

12/3/2008 8:22:00 AM

0

jason.cipriani@gmail.com wrote:
> On Dec 3, 1:47 am, Alan Johnson <aw...@yahoo.com> wrote:

[lots of cutting]

>> 1. Don't use singletons. Ever. Pretty much all of the value of the GoF
>> Design Patterns book is negated by the fact that they chose to
>> legitimize Singleton as a design pattern. Singleton is just a fancy
>> name for global variable. We should call it the Global Variable
>> (anti)Pattern.
>>

> greatly simplifies a lot of application code. And you are correct, in
> this case it basically is, in fact, a global variable.
>

Both of you are not correct. The singleton is not a global variable.

TheClass* instance = NULL;
TheClass * GetInstance()
{
if ( NULL == instance )
{
instance = new TheClass;
}
return instance;
}

In this case, the instance is created when the function GetInstance()
gets called the first time, while global variables gets created before
entering main()

James Kanze

12/3/2008 9:44:00 AM

0

On Dec 3, 7:47 am, Alan Johnson <aw...@yahoo.com> wrote:
> jason.cipri...@gmail.com wrote:
> > I have a C++-specific question about thread-safe singleton instances.
> > There's a trivial example here:

> >http://www.bombaydigital.com/arenared/20...

> > That goes like this, very simple and straightforward:

> > static Mutex mutex; static TheClass *instance;

> > static TheClass * getInstance () { MutexLocker lock(mutex); if
> > (!instance) instance = new TheClass(); return instance; }

> > The example then goes on to talk about how double-check
> > locking is broken, etc. My question is pretty much this: Is
> > C++ static initialization thread-safe? If not, then how does
> > the above example safely use "mutex"? If so, then what is
> > wrong with this:

> > static TheClass instance; // not a pointer

> > static TheClass * getInstance () { return &instance; // it's
> > correctly initialized? }

> > The reason I ask is I almost never see it done like that, I
> > always see blog entries and articles that say the same thing
> > "store instance in a pointer, use a mutex to protect, and
> > p.s. double-checked locking is broken". It seems like doing
> > it lock-free is made out to be a hard problem, so *if*
> > having a static instance works (but I don't know if it does,
> > that's my question), then why doesn't anybody ever suggest
> > it?

> 1. Don't use singletons. Ever. Pretty much all of the value
> of the GoF Design Patterns book is negated by the fact that
> they chose to legitimize Singleton as a design pattern.
> Singleton is just a fancy name for global variable. We should
> call it the Global Variable (anti)Pattern.

And there are valid reasons for using it. Some things must be
inherently unique in a process.

> 3. Double checked locking works without memory fencing on
> x86:http://bartoszmilewski.wordpress.com/2008/11/05/who-ordered......

The author says that it works without fences, but he doesn't
give any reference to anything which guarantees it. (From a
quick glance at the AMD document, it looks like it might be
safe, but I'd need more analysis to be sure.)

> Thus, your main opponent in the optimizer.

> 4. Whether or not the construction of a static variable is
> threadsafe depends mostly on the implementation (the standard
> says nothing about it). gcc has an option
> =fno-threadsafe-statics to turn off the extra code emitted to
> make local statics thread safe. I guess one could extrapolate
> that by default local statics are thread safe in gcc (though I
> have no idea if this is actually true).

Not that the g++ implementation of this is broken on some
processors.

James Kanze

12/3/2008 9:54:00 AM

0

On Dec 3, 1:25 am, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.com> wrote:
> I have a C++-specific question about thread-safe singleton instances.
> There's a trivial example here:

> http://www.bombaydigital.com/arenared/20...

> That goes like this, very simple and straightforward:

> static Mutex mutex;
> static TheClass *instance;

> static TheClass * getInstance () {
> MutexLocker lock(mutex);
> if (!instance)
> instance = new TheClass();
> return instance;
> }

> The example then goes on to talk about how double-check
> locking is broken, etc. My question is pretty much this: Is
> C++ static initialization thread-safe?

No.

It's actually very hard to answer concretely here. Objects with
static lifetime in class or namespace scope are constructed
before main is entered, so if threads aren't started until then,
you're OK. Except that if getInstance is called before then,
you may have an order of initialization problem. And the
guarantee of construction before main is entered doesn't apply
to dynamically linked objects (which aren't addressed by the
standard, but then, neither is multi-threading).

My usual solution here is something like:

namespace {
TheClass* ourInstance = &TheClass::instance() ;
}

TheClass&
TheClass::instance()
{
if ( ourInstance == NULL ) {
ourInstance = new TheClass ;
// or
static TheClass theOneAndOnly ;
ourInstance = &theOneAndOnly ;
}
return *ourInstance ;
}

The initializer for the static variable ensures that
TheClass::instance is called at least once before main is
entered, and once you've returned from a call to
TheClass::instance(), the function is thread safe without locks.

> If not, then how does the above example safely use "mutex"? If
> so, then what is wrong with this:

> static TheClass instance; // not a pointer

> static TheClass * getInstance () {
> return &instance; // it's correctly initialized?
> }

> The reason I ask is I almost never see it done like that, I
> always see blog entries and articles that say the same thing
> "store instance in a pointer, use a mutex to protect, and p.s.
> double-checked locking is broken". It seems like doing it
> lock-free is made out to be a hard problem, so *if* having a
> static instance works (but I don't know if it does, that's my
> question), then why doesn't anybody ever suggest it?

Because it's open to order of initialization issues.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Alan Johnson

12/3/2008 10:51:00 AM

0

anon wrote:
> jason.cipriani@gmail.com wrote:
>> On Dec 3, 1:47 am, Alan Johnson <aw...@yahoo.com> wrote:
>
> [lots of cutting]
>
>>> 1. Don't use singletons. Ever. Pretty much all of the value of
>>> the GoF Design Patterns book is negated by the fact that they
>>> chose to legitimize Singleton as a design pattern. Singleton is
>>> just a fancy name for global variable. We should call it the
>>> Global Variable (anti)Pattern.
>>>
>
>> greatly simplifies a lot of application code. And you are correct,
>> in this case it basically is, in fact, a global variable.
>>
>
> Both of you are not correct. The singleton is not a global variable.
>
> TheClass* instance = NULL; TheClass * GetInstance() { if ( NULL ==
> instance ) { instance = new TheClass; } return instance; }
>
> In this case, the instance is created when the function GetInstance()
> gets called the first time, while global variables gets created
> before entering main()

That still has all the negative effects of a global variable. To name a few
= hidden dependencies in functions that use it
= persistent global state
- tight coupling between anything that uses it

It also brings its own set of new problems.
= multiple responsibilities in one class (responsible for limiting the
number of instances and for whatever the class is normally supposed to do)
= the whole cluster of problems around thread-safe lazy initialization
- someday you will want more than one (you always do)
- typically unable to derive from the singleton class (without heroic
effort)

You would typically be better off just declaring a global
variable and using that instead.

--
Alan Johnson