Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Threadsafe singletons

9 views
Skip to first unread message

David Barrett-Lennard

unread,
Jul 30, 2006, 11:01:33 PM7/30/06
to
There have been extensive discussions on comp.lang.c++.moderated and
comp.programming.threads about the problem of writing a threadsafe
singleton. Most of this centers around the double checked idiom, known
to be broken.

The following approach avoids the problem entirely.

///////////// header
class MySingleton
{
public:
static MySingleton& GetInstance();
private:
MySingleton();
};

////////////// cpp
MySingleton& MySingleton::GetInstance()
{
static MySingleton s;
return s;
}

static struct InitMySingleton
{
InitMySingleton() { MySingleton::GetInstance(); }
} s_init;


The GetInstance() function employs the lazy creation approach.
However, the intention is not to avoid consuming resources. In fact
the static InitMySingleton instance is used to force the singleton to
be eagerly initialized before main() begins.

It is assumed that no additional threads are created until after main()
begins. Therefore before main() only one thread can call
GetInstance(). Even if other static initialization code causes
GetInstance() to be called there is no threading issue. Furthermore
the lazy creation within GetInstance() ensures that the MySingleton
object is properly constructed before it is first used.

After main() is called, threads may be created that call
GetInstance(). All threads will find that the MySingleton object has
already been fully constructed, even in a multiprocessor machine. Note
that thread creation implicitly involves the necessary memory barriers.

MySingleton can choose to use a mutex member if it is mutative.
Otherwise it may provide shared read access without any mutex at all.


Cheers,
David Barrett-Lennard


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Chris Thomasson

unread,
Jul 31, 2006, 8:10:44 AM7/31/06
to
"David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
news:1154313829.5...@p79g2000cwp.googlegroups.com...

> There have been extensive discussions on comp.lang.c++.moderated and
> comp.programming.threads about the problem of writing a threadsafe
> singleton. Most of this centers around the double checked idiom, known
> to be broken.

I assume you actually mean that there are a lot of existing implementations'

out there that happen to be "completely" broken... Correct?

The actual pattern itself it perfectly fine IMO, and can be successfully
implemented with assembly language and externally assembled into a library
with a coherent ABI and portable C interface; no doubt about it... IMHO,
most of the problems that are generally associated with double checked
locking seem to be related to compiler reordering, and of course, the
"apparent" widespread lack of knowledge wrt memory barrier functionality...

BTW, I think I heard Herb Sutter mention something about a Microsoft
compiler that can implement a DCL pattern without the use of an external
assembler... I believe they have assigned acquire/release semantics to the
volatile keyword; load.acquire, store.release... Humm... Does anybody know
fore sure if Microsoft compilers, for any Itanium architecture, actually
guard accesses to volatile variables with "explicit" memory barrier
instructions?


> The following approach avoids the problem entirely.

Yes. If your rules are followed, it will work... Thread creation provides
the necessarily #LoadStore|#StoreStore barrier, ie release semantics...
Indeed... Anyway, FWIW, here is a link to a quick discussion on atomically
thread-safe ad-hoc DCL implementation in x86:

http://groups.google.com/group/comp.programming.threads/msg/8ae09f9e9bea21b9
http://groups.google.com/group/comp.programming.threads/msg/1ac122ce09f3c4f6
http://groups.google.com/group/comp.programming.threads/msg/f2c59ced973e75dd
http://groups.google.com/group/comp.programming.threads/msg/731cd06e8c04f744
http://groups.google.com/group/comp.programming.threads/msg/d4f9b41bbadbff95

Enjoy...

;)

fluid...@yahoo.com

unread,
Jul 31, 2006, 8:24:52 AM7/31/06
to
Tell me if I have your idea correct because this isn't working for me.

/////////// singleton.h
class Singleton
{
char *name;

public:
static Singleton& GetInstance();

char *GetName() const { return name; }
void SetName(char *n) { name = n; }

private:
Singleton();
};

/////////// singleton.cpp
#include "singleton.h"

Singleton::Singleton()
{
}

/////////// main.cpp
#include "singleton.h"

#include <iostream>

Singleton& Singleton::GetInstance()
{
static Singleton s;
return s;
}

static struct InitSingleton
{
InitSingleton()
{
Singleton s = Singleton::GetInstance();
s.SetName("Super Duper");
}
} s_init;

int main()
{
Singleton singleton = Singleton::GetInstance();

std::cout << "The singleton's name is: " <<
singleton.GetName() << std::endl;

return 0;
}

I'm not getting a "Super Duper" Singleton

Earl Purple

unread,
Jul 31, 2006, 8:46:56 AM7/31/06
to

David Barrett-Lennard wrote:


> ///////////// header
> class MySingleton
> {
> public:
> static MySingleton& GetInstance();
> private:
> MySingleton();
> };
>
> ////////////// cpp
> MySingleton& MySingleton::GetInstance()
> {
> static MySingleton s;
> return s;
> }

Is this not threadsafe anyway (assuming you have a compliant
compiler?). There should be only one instance of a static regardless of
race conditions.

> static struct InitMySingleton
> {
> InitMySingleton() { MySingleton::GetInstance(); }
> } s_init;
>
>
> The GetInstance() function employs the lazy creation approach.
> However, the intention is not to avoid consuming resources. In fact
> the static InitMySingleton instance is used to force the singleton to
> be eagerly initialized before main() begins.

Yes but then you may as well just use a static instance of MySingleton
instead. s_init has to exist of course in a compilation unit
somewhere, but why not just the MySingleton instance there?

Of course there is no way to catch any exceptions should MySingleton's
constructor throw one so you'd better make sure it doesn't.

Also, being created as an instance rather than a pointer means there is
no deterministic destruction. Assuming the destructor is trivial (and
note that trivial here doesn't just mean implicit, it means it really
deletes nothing, no members etc). you have nothing to worry about. If
it is not then there are possibilities of undefined behaviour on
destruction. You may not care if your app seg-faults when it is being
closed down anyway, but it's not really ideal behaviour.

> It is assumed that no additional threads are created until after main()
> begins. Therefore before main() only one thread can call
> GetInstance(). Even if other static initialization code causes
> GetInstance() to be called there is no threading issue. Furthermore
> the lazy creation within GetInstance() ensures that the MySingleton
> object is properly constructed before it is first used.

But it isn't lazy creation. Lazy creation means creating when first
required. Here it is created before main is called .Now it may be that
is the behaviour you want - after all once your app is in "full swing"
you might not be able to afford the time-delay of lazy creation whilst
you do afford the time on start-up (when no clients have yet connected
to your server). Of course that might mean you are loading resources
that are never used, but that is for you to determine.

> After main() is called, threads may be created that call
> GetInstance(). All threads will find that the MySingleton object has
> already been fully constructed, even in a multiprocessor machine. Note
> that thread creation implicitly involves the necessary memory barriers.
>
> MySingleton can choose to use a mutex member if it is mutative.
> Otherwise it may provide shared read access without any mutex at all.

Well that is now implementation detail for your class, but ask yourself
if it really does need to be a singleton. I used to use a lot of
singletons. Now I have just 2 - and that is really one too many. One of
my singletons is a collection of all the libraries that have been
opened with dlopen(), the other is there to handle signals to ensure
clean shutdown, ensure all the logs are flushed, etc. Even then the
second one uses objects that are in libraries held by the first so it
has to be "cleared" first. So one must call an implicit clear() on it
to ensure deterministic destruction.

Now what might be a better approach for you here is to have the inner
object (the singleton) be a pointer which is created by the static that
wraps it, and that be a manager for ALL your singletons Of course that
means you need to know what they all are. But it will ensure
deterministic destruction.

But now, hey, what about the issue of catching the exceptions? Well
that's simple, don't make this wrapper a static at all, make it an
instance inside your main() function.

Hey, not sure where this will lead but maybe we'll end up eliminating
pretty much all your singletons...

Matthias Hofmann

unread,
Jul 31, 2006, 9:05:02 AM7/31/06
to
"David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
news:1154313829.5...@p79g2000cwp.googlegroups.com...

> It is assumed that no additional threads are created until after main()
> begins. Therefore before main() only one thread can call
> GetInstance(). Even if other static initialization code causes
> GetInstance() to be called there is no threading issue.

You mean *dynamic* initialization code, don't you?

> Furthermore
> the lazy creation within GetInstance() ensures that the MySingleton
> object is properly constructed before it is first used.
>
> After main() is called, threads may be created that call
> GetInstance().

Yes, *after* main() has been called. But what about calling
MySingleton::GetInstance() *before* main() is called? There is no guarantee
that InitMySingleton's constructor will be called before that happens.

> All threads will find that the MySingleton object has
> already been fully constructed, even in a multiprocessor machine.

If you do not use MySingleton *before* main() is called, the object will
always be fully constructed. Otherwise, the use of InitMySingleton won't
help you much.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

kanze

unread,
Jul 31, 2006, 9:04:14 AM7/31/06
to
David Barrett-Lennard wrote:
> There have been extensive discussions on
> comp.lang.c++.moderated and comp.programming.threads about the
> problem of writing a threadsafe singleton. Most of this
> centers around the double checked idiom, known to be broken.

> The following approach avoids the problem entirely.

Maybe. (Probably, with most implementations, in practice.
Guarantees are hard to come by, however.)

> ///////////// header
> class MySingleton
> {
> public:
> static MySingleton& GetInstance();
> private:
> MySingleton();
> };

> ////////////// cpp
> MySingleton& MySingleton::GetInstance()
> {
> static MySingleton s;
> return s;
> }

> static struct InitMySingleton
> {
> InitMySingleton() { MySingleton::GetInstance(); }
> } s_init;

> The GetInstance() function employs the lazy creation approach.
> However, the intention is not to avoid consuming resources.
> In fact the static InitMySingleton instance is used to force
> the singleton to be eagerly initialized before main() begins.

> It is assumed that no additional threads are created until
> after main() begins. Therefore before main() only one thread
> can call GetInstance(). Even if other static initialization
> code causes GetInstance() to be called there is no threading
> issue. Furthermore the lazy creation within GetInstance()
> ensures that the MySingleton object is properly constructed
> before it is first used.

I've often used something similar; I've even posted about it
once or twice here. In my case, I use an explicit pointer and
new, but the principle is the same. Except that I know how an
explicit pointer and new work---I can only guess as to how the
compiler ensures creation on only the first call to GetInstance.
At least some compilers, in a threaded environment, use
something like pthread_once to initialize the variable, so
constructing it before entering main isn't necessary. At the
other extreme, other compilers document nothing, and may use
some technique which isn't thread safe. In the absense of any
specific guarantees, I prefer to avoid counting too much on what
the compiler does here.

My own technique is basically:

static MySingleton* ourInstance = &MySingleton::instance() ;

MySingleton&
MySingleton::instance()
{
if ( ourInstance == NULL ) {
ourInstance = new MySingleton ;
}
return *ourInstance ;
}

Formally, there is no guarantee that static variables are
constructed before entering main, so you have no guaranteed that
your s_init object (or my ourInstance pointer) will be
initialized before entering main. In practice, it will be
*UNLESS* the singleton is in a dynamically linked component.
As a general rule, I think you're safe, but only as the
consequences of a series of conditions:

-- you don't return from dlopen (or it's Windows equivalent)
before the initialization has taken place in the thread
which called dlopen, and the calling thread is guaranteed to
see the correct memory values, and

-- other threads can't know that the object has been loaded
unless you tell them, and telling them involves system
requests which synchronize memory.

Pay particular attention to this second point, because it might
not hold for some lock-free algorithms.

> After main() is called, threads may be created that call
> GetInstance(). All threads will find that the MySingleton
> object has already been fully constructed, even in a
> multiprocessor machine. Note that thread creation implicitly
> involves the necessary memory barriers.

> MySingleton can choose to use a mutex member if it is
> mutative. Otherwise it may provide shared read access without
> any mutex at all.

If it is mutative, and represents the correct level of
granularity for locking, another alternative is to acquire the
lock before checking for null, and to return a boost::shared_ptr
to the object, whose "destructor" frees the lock. You need one
lock anyway, this avoids a second.

--
James Kanze GABI Software
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

Matthias Hofmann

unread,
Jul 31, 2006, 10:18:11 AM7/31/06
to
<fluid...@yahoo.com> schrieb im Newsbeitrag
news:1154336088.5...@i3g2000cwc.googlegroups.com...

> static struct InitSingleton
> {
> InitSingleton()
> {
> Singleton s = Singleton::GetInstance();
> s.SetName("Super Duper");

You are setting the name of a copy. Change it to the following and it will
work:

// Note the use of a reference.
Singleton& s = Singleton::GetInstance();
s.SetName("Super Duper");

This error would not have occurred if the copy constructor of Singleton had
been declared private, as should be the case for a singleton.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

David Barrett-Lennard

unread,
Jul 31, 2006, 10:18:40 AM7/31/06
to

Earl Purple wrote:

<snip>

> > The GetInstance() function employs the lazy creation approach.
> > However, the intention is not to avoid consuming resources. In fact
> > the static InitMySingleton instance is used to force the singleton to
> > be eagerly initialized before main() begins.
>
> Yes but then you may as well just use a static instance of MySingleton
> instead. s_init has to exist of course in a compilation unit
> somewhere, but why not just the MySingleton instance there?

I'm allowing for MySingleton::GetInstance() to be called many times
before main() begins. My implementation solves an order of creation
problem that could otherwise arise using your suggestion.

> Of course there is no way to catch any exceptions should MySingleton's
> constructor throw one so you'd better make sure it doesn't.

Yes

> Also, being created as an instance rather than a pointer means there is
> no deterministic destruction. Assuming the destructor is trivial (and
> note that trivial here doesn't just mean implicit, it means it really
> deletes nothing, no members etc). you have nothing to worry about. If
> it is not then there are possibilities of undefined behaviour on
> destruction. You may not care if your app seg-faults when it is being
> closed down anyway, but it's not really ideal behaviour.

Yes. I rarely use singletons, and when I do the constructor and
destructor tend to be infallible.

> > It is assumed that no additional threads are created until after main()
> > begins. Therefore before main() only one thread can call
> > GetInstance(). Even if other static initialization code causes
> > GetInstance() to be called there is no threading issue. Furthermore
> > the lazy creation within GetInstance() ensures that the MySingleton
> > object is properly constructed before it is first used.
>
> But it isn't lazy creation. Lazy creation means creating when first
> required. Here it is created before main is called .

It is lazy and eager! See above : Before main() begins the laziness is
important to solve order of construction dependencies.

> Now it may be that
> is the behaviour you want - after all once your app is in "full swing"
> you might not be able to afford the time-delay of lazy creation whilst
> you do afford the time on start-up (when no clients have yet connected
> to your server). Of course that might mean you are loading resources
> that are never used, but that is for you to determine.

I'm a bit suspicious of singletons that do things like open files. If
it were really warranted I would probably explicitly create and destroy
the singleton - perhaps from main. That would also solve the threading
issues.

> > After main() is called, threads may be created that call
> > GetInstance(). All threads will find that the MySingleton object has
> > already been fully constructed, even in a multiprocessor machine. Note
> > that thread creation implicitly involves the necessary memory barriers.
> >
> > MySingleton can choose to use a mutex member if it is mutative.
> > Otherwise it may provide shared read access without any mutex at all.
>
> Well that is now implementation detail for your class, but ask yourself
> if it really does need to be a singleton. I used to use a lot of
> singletons. Now I have just 2 - and that is really one too many. One of
> my singletons is a collection of all the libraries that have been
> opened with dlopen(), the other is there to handle signals to ensure
> clean shutdown, ensure all the logs are flushed, etc. Even then the
> second one uses objects that are in libraries held by the first so it
> has to be "cleared" first. So one must call an implicit clear() on it
> to ensure deterministic destruction.

I agree that singletons should rarely be used.

David Barrett-Lennard

unread,
Jul 31, 2006, 10:19:01 AM7/31/06
to

Matthias Hofmann wrote:
> "David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
> news:1154313829.5...@p79g2000cwp.googlegroups.com...
>
> > It is assumed that no additional threads are created until after main()
> > begins. Therefore before main() only one thread can call
> > GetInstance(). Even if other static initialization code causes
> > GetInstance() to be called there is no threading issue.
>
> You mean *dynamic* initialization code, don't you?

Are these precise formal terms? I'm referring to the code that runs
when constructors of static objects execute before main() begins.

> > Furthermore
> > the lazy creation within GetInstance() ensures that the MySingleton
> > object is properly constructed before it is first used.
> >
> > After main() is called, threads may be created that call
> > GetInstance().
>
> Yes, *after* main() has been called. But what about calling
> MySingleton::GetInstance() *before* main() is called? There is no
guarantee
> that InitMySingleton's constructor will be called before that happens.

So what? The program will behave correctly. There is no racing
condition. MySingleton is created before it is first used
(irrespective of when GetInstance() is first called before main()
begins), as required.

> > All threads will find that the MySingleton object has
> > already been fully constructed, even in a multiprocessor machine.
>
> If you do not use MySingleton *before* main() is called, the object will
> always be fully constructed.

Yes, creation is initially lazy then changes to eager!

> Otherwise, the use of InitMySingleton won't
> help you much.

No, forcing (eager) creation avoids subsequent threading issues.

Cheers,
David Barrett-Lennard

David Barrett-Lennard

unread,
Jul 31, 2006, 10:17:38 AM7/31/06
to

Chris Thomasson wrote:
> "David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
> news:1154313829.5...@p79g2000cwp.googlegroups.com...
> > There have been extensive discussions on comp.lang.c++.moderated and
> > comp.programming.threads about the problem of writing a threadsafe
> > singleton. Most of this centers around the double checked idiom, known
> > to be broken.
>
> I assume you actually mean that there are a lot of existing
implementations'
>
> out there that happen to be "completely" broken... Correct?

Yes, and also AFAIK there doesn't exist a platform independent
implementation.

> The actual pattern itself it perfectly fine IMO, and can be successfully
> implemented with assembly language and externally assembled into a library
> with a coherent ABI and portable C interface; no doubt about it... IMHO,
> most of the problems that are generally associated with double checked
> locking seem to be related to compiler reordering, and of course, the
> "apparent" widespread lack of knowledge wrt memory barrier
functionality...

My solution is *much* simpler and it's platform independent.


Cheers,
David Barrett-Lennard

David Barrett-Lennard

unread,
Jul 31, 2006, 10:10:26 AM7/31/06
to

Did it crash? Your constructor doesn't initialise the 'name' member
and the statement s.SetName("Super Duper") is setting the name of a
copy of the class (not the original).

Rather than

> Singleton s = Singleton::GetInstance();

you should instead write

Singleton& s = Singleton::GetInstance();

I suggest you make the copy constructor and assignment operator of your
Singleton class private to avoid copying.

BTW I also suggest you use a proper string member rather than simply
alias a null terminated string with a char pointer. It's rather
dangerous.

Cheers,
David Barrett-Lennard

Marcin 'Qrczak' Kowalczyk

unread,
Jul 31, 2006, 10:38:15 AM7/31/06
to
Followup-To: comp.programming.threads

"Earl Purple" <earlp...@gmail.com> writes:

>> MySingleton& MySingleton::GetInstance()
>> {
>> static MySingleton s;
>> return s;
>> }
>
> Is this not threadsafe anyway (assuming you have a compliant
> compiler?). There should be only one instance of a static regardless
> of race conditions.

Compliant to what? C++ says nothing about threads, and POSIX says
nothing about C++.

I think a good C++/threads standard should make this thread-safe, but
there is currently no standard to guarantee that. GCC seems to make it
thread-safe (it calls some __cxa_guard_acquire, __cxa_guard_release
and __cxa_atexit functions instead of just using a private boolean flag);
I don't know about other implementations.

--
__("< Marcin Kowalczyk
\__/ qrc...@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/

Marcin 'Qrczak' Kowalczyk

unread,
Jul 31, 2006, 10:39:38 AM7/31/06
to
Followup-To: comp.programming.threads

"Chris Thomasson" <cri...@comcast.net> writes:

> The actual pattern itself it perfectly fine IMO, and can be successfully
> implemented with assembly language and externally assembled into a library

> with a coherent ABI and portable C interface; no doubt about it... IMHO,
> most of the problems that are generally associated with double checked
> locking seem to be related to compiler reordering, and of course, the
> "apparent" widespread lack of knowledge wrt memory barrier
functionality...

In the case of GCC external assembly should not be necessary. Appropriate
annotations of assembler snippets (about clobbering memory, or volatile
which prevents optimizing it out) are enough.

If you claim they are not enough, please show an example.

--
__("< Marcin Kowalczyk
\__/ qrc...@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

David Barrett-Lennard

unread,
Jul 31, 2006, 11:00:44 AM7/31/06
to

Good point. I didn't know some compilers would do that.

> At the
> other extreme, other compilers document nothing, and may use
> some technique which isn't thread safe. In the absense of any
> specific guarantees, I prefer to avoid counting too much on what
> the compiler does here.
>
> My own technique is basically:
>
> static MySingleton* ourInstance = &MySingleton::instance() ;
>
> MySingleton&
> MySingleton::instance()
> {
> if ( ourInstance == NULL ) {
> ourInstance = new MySingleton ;
> }
> return *ourInstance ;
> }

How is it deleted?

> Formally, there is no guarantee that static variables are
> constructed before entering main, so you have no guaranteed that
> your s_init object (or my ourInstance pointer) will be
> initialized before entering main.

Really! Are you referring to the C++ standard?

> In practice, it will be
> *UNLESS* the singleton is in a dynamically linked component.

> As a general rule, I think you're safe, but only as the
> consequences of a series of conditions:
>
> -- you don't return from dlopen (or it's Windows equivalent)
> before the initialization has taken place in the thread
> which called dlopen, and the calling thread is guaranteed to
> see the correct memory values, and
>
> -- other threads can't know that the object has been loaded
> unless you tell them, and telling them involves system
> requests which synchronize memory.

In Windows if a DLL containing the definition of MySingleton is loaded
after main() begins with a call to LoadLibrary(), then AFAIK
MySingleton::GetInstance() will be called before LoadLibrary() returns
because of the static initialisation. So the singleton is fully
constructed before any attempt is made to bind a function call to
MySingleton::GetInstance().

>
> Pay particular attention to this second point, because it might
> not hold for some lock-free algorithms.
>
> > After main() is called, threads may be created that call
> > GetInstance(). All threads will find that the MySingleton
> > object has already been fully constructed, even in a
> > multiprocessor machine. Note that thread creation implicitly
> > involves the necessary memory barriers.
>
> > MySingleton can choose to use a mutex member if it is
> > mutative. Otherwise it may provide shared read access without
> > any mutex at all.
>
> If it is mutative, and represents the correct level of
> granularity for locking, another alternative is to acquire the
> lock before checking for null, and to return a boost::shared_ptr
> to the object, whose "destructor" frees the lock. You need one
> lock anyway, this avoids a second.

I presume I misunderstand you because it seems like you will have a
problem accessing an uninitialised lock if the singleton is accessed
before main() begins.


Cheers,
David Barrett-Lennard

Matthias Hofmann

unread,
Jul 31, 2006, 11:56:41 AM7/31/06
to
"David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
news:1154354445.4...@75g2000cwc.googlegroups.com...

>
> Matthias Hofmann wrote:
> > "David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
> > news:1154313829.5...@p79g2000cwp.googlegroups.com...
> >
> > > It is assumed that no additional threads are created until after
main()
> > > begins. Therefore before main() only one thread can call
> > > GetInstance(). Even if other static initialization code causes
> > > GetInstance() to be called there is no threading issue.
> >
> > You mean *dynamic* initialization code, don't you?
>
> Are these precise formal terms? I'm referring to the code that runs
> when constructors of static objects execute before main() begins.

The terms "static initialization" and "dynamic initialization" are defined
in section 3.6.2/1 of the standard.

> > > Furthermore
> > > the lazy creation within GetInstance() ensures that the MySingleton
> > > object is properly constructed before it is first used.
> > >
> > > After main() is called, threads may be created that call
> > > GetInstance().
> >
> > Yes, *after* main() has been called. But what about calling
> > MySingleton::GetInstance() *before* main() is called? There is no
> guarantee
> > that InitMySingleton's constructor will be called before that happens.
>
> So what? The program will behave correctly. There is no racing
> condition. MySingleton is created before it is first used
> (irrespective of when GetInstance() is first called before main()
> begins), as required.

My mistake. You are right.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jul 31, 2006, 11:57:38 AM7/31/06
to
"David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
news:1154356686.1...@s13g2000cwa.googlegroups.com...

> > I've often used something similar; I've even posted about it
> > once or twice here. In my case, I use an explicit pointer and
> > new, but the principle is the same. Except that I know how an
> > explicit pointer and new work---I can only guess as to how the
> > compiler ensures creation on only the first call to GetInstance.
> > At least some compilers, in a threaded environment, use
> > something like pthread_once to initialize the variable, so
> > constructing it before entering main isn't necessary.
>
> Good point. I didn't know some compilers would do that.

What exactly is the problem with creation of a local static object and
threads?

> > At the
> > other extreme, other compilers document nothing, and may use
> > some technique which isn't thread safe. In the absense of any
> > specific guarantees, I prefer to avoid counting too much on what
> > the compiler does here.
> >
> > My own technique is basically:
> >
> > static MySingleton* ourInstance = &MySingleton::instance() ;
> >
> > MySingleton&
> > MySingleton::instance()
> > {
> > if ( ourInstance == NULL ) {
> > ourInstance = new MySingleton ;
> > }
> > return *ourInstance ;
> > }
>
> How is it deleted?

This interests me too.

> > Formally, there is no guarantee that static variables are
> > constructed before entering main, so you have no guaranteed that
> > your s_init object (or my ourInstance pointer) will be
> > initialized before entering main.
>
> Really! Are you referring to the C++ standard?

It is described in 3.6.2/3. If I understand this part of the standard
correctly, it does, however, guarantee that the ourInstance pointer will be
initialized before it is first used.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jul 31, 2006, 11:57:17 AM7/31/06
to
"David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
news:1154351660.5...@m73g2000cwd.googlegroups.com...

> BTW I also suggest you use a proper string member rather than simply
> alias a null terminated string with a char pointer. It's rather
> dangerous.

What could happen? The only thing I can imagine is using the char pointer to
modify the string literal. This can be fixed by using a pointer to a const
char.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Victor Bazarov

unread,
Jul 31, 2006, 3:31:45 PM7/31/06
to
fluid...@yahoo.com wrote:
> Tell me if I have your idea correct because this isn't working for me.
>
> /////////// singleton.h
> class Singleton
> {
> char *name;
>

Add here:

Singleton(Singleton const&);
Singleton& operator(Singleton const&);

> public:
> static Singleton& GetInstance();
>
> char *GetName() const { return name; }
> void SetName(char *n) { name = n; }
>
> private:
> Singleton();
> };
>
> /////////// singleton.cpp
> #include "singleton.h"
>
> Singleton::Singleton()
> {
> }
>
> /////////// main.cpp
> #include "singleton.h"
>
> #include <iostream>
>
> Singleton& Singleton::GetInstance()
> {
> static Singleton s;
> return s;
> }
>
> static struct InitSingleton
> {
> InitSingleton()
> {
> Singleton s = Singleton::GetInstance();

Replase the line above with

Singleton &s = Singleton::GetInstance();

> s.SetName("Super Duper");
> }
> } s_init;
>
> int main()
> {
> Singleton singleton = Singleton::GetInstance();

Replace the line above with

Singleton & singleton = Singleton::GetInstance();

>
> std::cout << "The singleton's name is: " <<
> singleton.GetName() << std::endl;
>
> return 0;
> }
>
> I'm not getting a "Super Duper" Singleton

You are simply not getting a singleton with your code.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

David Barrett-Lennard

unread,
Jul 31, 2006, 8:37:23 PM7/31/06
to

Matthias Hofmann wrote:
> "David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
> news:1154351660.5...@m73g2000cwd.googlegroups.com...
>
> > BTW I also suggest you use a proper string member rather than simply
> > alias a null terminated string with a char pointer. It's rather
> > dangerous.
>
> What could happen? The only thing I can imagine is using the char pointer
to
> modify the string literal. This can be fixed by using a pointer to a const
> char.

SetName() is a public function. A programmer may accidentally do this

void foo()
{
std::string s = bar() + "$";
Singleton::GetInstance().SetName(s.c_str());
}

Note BTW that for a mutative singleton to be threadsafe it would need a
mutex.

Cheers,
David Barrett-Lennard

David Barrett-Lennard

unread,
Jul 31, 2006, 8:39:21 PM7/31/06
to

Matthias Hofmann wrote:
> "David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
> news:1154356686.1...@s13g2000cwa.googlegroups.com...
>
> > > I've often used something similar; I've even posted about it
> > > once or twice here. In my case, I use an explicit pointer and
> > > new, but the principle is the same. Except that I know how an
> > > explicit pointer and new work---I can only guess as to how the
> > > compiler ensures creation on only the first call to GetInstance.
> > > At least some compilers, in a threaded environment, use
> > > something like pthread_once to initialize the variable, so
> > > constructing it before entering main isn't necessary.
> >
> > Good point. I didn't know some compilers would do that.
>
> What exactly is the problem with creation of a local static object and
> threads?

I wanted a singleton that is threadsafe yet doesn't necessarily require
synchronisation primitives in order to access it. This is particularly
beneficial for immutable singletons that support shared read access.

I presume the performance benefit would be lost if a compiler used
something like pthread_once to initialize the static local variable
within GetInstance().

It's annoying that fundamental differences between compilers can mean
going for a lowest common denominator when writing (efficient) platform
independent code!


Cheers,
David Barrett-Lennard

Gene Bushuyev

unread,
Aug 1, 2006, 8:14:35 AM8/1/06
to
"David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
news:1154313829.5...@p79g2000cwp.googlegroups.com...
[...]

> The GetInstance() function employs the lazy creation approach.
> However, the intention is not to avoid consuming resources. In fact
> the static InitMySingleton instance is used to force the singleton to
> be eagerly initialized before main() begins.

You don't have any guarantee that either one of your objects is
itinitialized
before main (3.6.2/3). The standard only requires that they are initialized
before the first use, neither static MySingleton nor s_init are used before
main() in your example.

--
Gene Bushuyev (www.gbresearch.com)
----------------------------------------------------------------
To see what is in front of one's nose needs a constant struggle ~ George
Orwell

Francis Glassborow

unread,
Aug 1, 2006, 8:25:58 AM8/1/06
to
In article <1154389322.7...@b28g2000cwb.googlegroups.com>,
David Barrett-Lennard <dav...@iinet.net.au> writes

>I wanted a singleton that is threadsafe yet doesn't necessarily require
>synchronisation primitives in order to access it. This is particularly
>beneficial for immutable singletons that support shared read access.

Where is the problem if it is immutable?


--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects

kanze

unread,
Aug 1, 2006, 8:57:32 AM8/1/06
to
Matthias Hofmann wrote:
> "David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
> news:1154351660.5...@m73g2000cwd.googlegroups.com...

> > BTW I also suggest you use a proper string member rather
> > than simply alias a null terminated string with a char
> > pointer. It's rather dangerous.

> What could happen? The only thing I can imagine is using the
> char pointer to modify the string literal. This can be fixed
> by using a pointer to a const char.

void
muckItUp()
{
char doh[] = "How long will I exist?" ;
Singleton::GetInstance().SetName( doh ) ;
}

I wouldn't like to use the singleton after a call to muckItUp.

--
James Kanze GABI Software
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

kanze

unread,
Aug 1, 2006, 8:58:57 AM8/1/06
to
Matthias Hofmann wrote:
> "David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
> news:1154354445.4...@75g2000cwc.googlegroups.com...

> > Matthias Hofmann wrote:
> > > "David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
> > > news:1154313829.5...@p79g2000cwp.googlegroups.com...

> > > > It is assumed that no additional threads are created until after
main()
> > > > begins. Therefore before main() only one thread can call
> > > > GetInstance(). Even if other static initialization code causes
> > > > GetInstance() to be called there is no threading issue.

> > > You mean *dynamic* initialization code, don't you?

> > Are these precise formal terms? I'm referring to the code that runs
> > when constructors of static objects execute before main() begins.

> The terms "static initialization" and "dynamic initialization" are defined
> in section 3.6.2/1 of the standard.

Note that confusion is easy because both refer to objects with
static lifetimes. It's not just in the language itself that the
word static is overly overloaded.

--
James Kanze GABI Software
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

kanze

unread,
Aug 1, 2006, 8:56:05 AM8/1/06
to
Chris Thomasson wrote:
> "David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
> news:1154313829.5...@p79g2000cwp.googlegroups.com...

> > There have been extensive discussions on
> > comp.lang.c++.moderated and comp.programming.threads about
> > the problem of writing a threadsafe singleton. Most of this
> > centers around the double checked idiom, known to be broken.

> I assume you actually mean that there are a lot of existing
> implementations' out there that happen to be "completely"
> broken... Correct?

I think he means that any implementation written purely in C++
is broken.

> The actual pattern itself it perfectly fine IMO, and can be
> successfully implemented with assembly language and externally
> assembled into a library with a coherent ABI and portable C
> interface; no doubt about it...

Or by inserting a few, critical asm parts in code that is
otherwise written in C++.

> IMHO, most of the problems that are generally associated with
> double checked locking seem to be related to compiler
> reordering, and of course, the "apparent" widespread lack of
> knowledge wrt memory barrier functionality...

The problem is not so much compiler reordering, although
admittedly, about 90% of the implementations I've seen have that
problem as well. The problem is that on most systems, you can't
get the memory barriers without either assembler or system
calls.

> BTW, I think I heard Herb Sutter mention something about a
> Microsoft compiler that can implement a DCL pattern without
> the use of an external assembler... I believe they have
> assigned acquire/release semantics to the volatile keyword;
> load.acquire, store.release... Humm... Does anybody know fore
> sure if Microsoft compilers, for any Itanium architecture,
> actually guard accesses to volatile variables with "explicit"
> memory barrier instructions?

That is, apparently, the case. Microsoft has given a useful
definition to volatile (in the case of multithreading). There
has been some discussion of making this standard. I'm not
really convinced as yet: volatile serves a very useful purpose
today, in embedded systems, precisely because it is so vaguely
defined. While I'm not against extending its semantics to be
useful for threading---arguably, this was intended as well
behind the vague wording that is now there---I don't want to see
it so rigorously defined that it looses its usefulness for
embedded systems.

> > The following approach avoids the problem entirely.

> Yes. If your rules are followed, it will work... Thread
> creation provides the necessarily #LoadStore|#StoreStore
> barrier, ie release semantics...

Under Posix compliant systems, it does. Presumably under others
as well, but I've yet to find a specification.

--
James Kanze GABI Software
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

kanze

unread,
Aug 1, 2006, 8:56:51 AM8/1/06
to
David Barrett-Lennard wrote:
> Chris Thomasson wrote:
> > "David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
> > news:1154313829.5...@p79g2000cwp.googlegroups.com...
> > > There have been extensive discussions on
> > > comp.lang.c++.moderated and comp.programming.threads about
> > > the problem of writing a threadsafe singleton. Most of
> > > this centers around the double checked idiom, known to be
> > > broken.

> > I assume you actually mean that there are a lot of existing
> > implementations' out there that happen to be "completely"
> > broken... Correct?

> Yes, and also AFAIK there doesn't exist a platform independent
> implementation.

Given that anything concerning threads is platform dependant:-).

The problem is that there isn't a portable solution even accross
e.g. Posix conformant systems.

> > The actual pattern itself it perfectly fine IMO, and can be
> > successfully implemented with assembly language and
> > externally assembled into a library with a coherent ABI and
> > portable C interface; no doubt about it... IMHO, most of the
> > problems that are generally associated with double checked
> > locking seem to be related to compiler reordering, and of
> > course, the "apparent" widespread lack of knowledge wrt
> > memory barrier functionality...

> My solution is *much* simpler and it's platform independent.

It's also faster:-). On the other hand, it introduces a certain
number of other constraints.

--
James Kanze GABI Software
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

kanze

unread,
Aug 1, 2006, 8:58:14 AM8/1/06
to
Earl Purple wrote:
> David Barrett-Lennard wrote:

> > ///////////// header
> > class MySingleton
> > {
> > public:
> > static MySingleton& GetInstance();
> > private:
> > MySingleton();
> > };

> > ////////////// cpp
> > MySingleton& MySingleton::GetInstance()
> > {
> > static MySingleton s;
> > return s;
> > }

> Is this not threadsafe anyway (assuming you have a compliant
> compiler?). There should be only one instance of a static
> regardless of race conditions.

Should is a very vague word. According to what standard? The
C++ standard says that as soon as you invoke pthread_create, or
something along those lines, you have undefined behavior. And
Posix doesn't say anything about it.

>From a quality of implementation point of view, I'd say you were
right. From a practical point of view, however, most compilers
don't seem to guarantee that this function is thread safe.

> > static struct InitMySingleton
> > {
> > InitMySingleton() { MySingleton::GetInstance(); }
> > } s_init;

> > The GetInstance() function employs the lazy creation
> > approach. However, the intention is not to avoid consuming
> > resources. In fact the static InitMySingleton instance is
> > used to force the singleton to be eagerly initialized before
> > main() begins.

> Yes but then you may as well just use a static instance of
> MySingleton instead. s_init has to exist of course in a
> compilation unit somewhere, but why not just the MySingleton
> instance there?

> Of course there is no way to catch any exceptions should
> MySingleton's constructor throw one so you'd better make sure
> it doesn't.

Or that it doesn't matter. Even programs which try to recover
from out of memory conditions punt when the condition occurs
during program start-up.

> Also, being created as an instance rather than a pointer means
> there is no deterministic destruction. Assuming the destructor
> is trivial (and note that trivial here doesn't just mean
> implicit, it means it really deletes nothing, no members etc).
> you have nothing to worry about. If it is not then there are
> possibilities of undefined behaviour on destruction. You may
> not care if your app seg-faults when it is being closed down
> anyway, but it's not really ideal behaviour.

The problem isn't just seg-faults. If we suppose that there
exist objects which have non-trivial destructors for reasons
other than just freeing memory (e.g. to delete a temporary
file), then they might not be called.

> > It is assumed that no additional threads are created until
> > after main() begins. Therefore before main() only one
> > thread can call GetInstance(). Even if other static
> > initialization code causes GetInstance() to be called there
> > is no threading issue. Furthermore the lazy creation within
> > GetInstance() ensures that the MySingleton object is
> > properly constructed before it is first used.

> But it isn't lazy creation. Lazy creation means creating when
> first required.

But that isn't part of the requirements. Singleton means that
there is a unique instance---only one. Lazy creation may or may
not be a side effect of this. If lazy creation is an essential
attribute, you need something else. With a different name.

---


James Kanze GABI Software
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

kanze

unread,
Aug 1, 2006, 9:09:44 AM8/1/06
to
Matthias Hofmann wrote:
> "David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
> news:1154356686.1...@s13g2000cwa.googlegroups.com...

> > > I've often used something similar; I've even posted about it
> > > once or twice here. In my case, I use an explicit pointer and
> > > new, but the principle is the same. Except that I know how an
> > > explicit pointer and new work---I can only guess as to how the
> > > compiler ensures creation on only the first call to GetInstance.
> > > At least some compilers, in a threaded environment, use
> > > something like pthread_once to initialize the variable, so
> > > constructing it before entering main isn't necessary.

> > Good point. I didn't know some compilers would do that.

> What exactly is the problem with creation of a local static
> object and threads?

The code generated by most compilers isn't thread safe.
Typically, there will be a hidden static bool which says whether
the object has been initialized or not; the compiler tests this,
and if it is false, calls the constructor, and then sets it to
true. If no particular steps are taken by the compiler, this
isn't thread safe.

[...]


> > > Formally, there is no guarantee that static variables are
> > > constructed before entering main, so you have no guaranteed that
> > > your s_init object (or my ourInstance pointer) will be
> > > initialized before entering main.

> > Really! Are you referring to the C++ standard?

> It is described in 3.6.2/3. If I understand this part of the
> standard correctly, it does, however, guarantee that the
> ourInstance pointer will be initialized before it is first
> used.

It guarantees that the pointer will be initialized before the
first use of anything defined in the translation unit. In
particular, it guarantees that the pointer will be initialized
before the first call to Singleton::GetInstance().

The standard requires this to work even in the presence of
circular dependencies, which is manifestly impossible. But it
doesn't matter, because no implementation takes advantage of the
rule; they all initialize before entering main (at least when
statically linked).

--
James Kanze GABI Software
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

kanze

unread,
Aug 1, 2006, 9:09:01 AM8/1/06
to
David Barrett-Lennard wrote:
> kanze wrote:
> > David Barrett-Lennard wrote:

[...]


> > At least some compilers, in a threaded environment, use
> > something like pthread_once to initialize the variable, so
> > constructing it before entering main isn't necessary.

> Good point. I didn't know some compilers would do that.

Only some. In my opinion, it should be required, once the C++
standard recognizes threads, but there are valid arguments both
ways: a function with a static variable is inherently not thread
safe, and presumably will be used only in a single threaded
environment, or when the client code has provided higher level
protection. In such cases, there is no threading issue in the
code, and the use of something like pthread_once is extra
overhead---you're paying for something you don't use. (But I'm
still in favor of doing the right thing.)

> > At the other extreme, other compilers document nothing, and
> > may use some technique which isn't thread safe. In the
> > absense of any specific guarantees, I prefer to avoid
> > counting too much on what the compiler does here.

> > My own technique is basically:

> > static MySingleton* ourInstance = &MySingleton::instance() ;

> > MySingleton&
> > MySingleton::instance()
> > {
> > if ( ourInstance == NULL ) {
> > ourInstance = new MySingleton ;
> > }
> > return *ourInstance ;
> > }

> How is it deleted?

It isn't. Generally, I don't want it to be; deleting it leads
to problems in the ordering of destructors (supposing it is used
in the destructor of an object with static lifetime).

> > Formally, there is no guarantee that static variables are
> > constructed before entering main, so you have no guaranteed
> > that your s_init object (or my ourInstance pointer) will be
> > initialized before entering main.

> Really! Are you referring to the C++ standard?

Yes. In practice, you can ignore it. The standard places
certain constraints on the order of initialization if it takes
place after entering main, and those constraints are, in fact,
impossible to meet.

> > In practice, it will be
> > *UNLESS* the singleton is in a dynamically linked component.

> > As a general rule, I think you're safe, but only as the
> > consequences of a series of conditions:

> > -- you don't return from dlopen (or it's Windows equivalent)
> > before the initialization has taken place in the thread
> > which called dlopen, and the calling thread is guaranteed to
> > see the correct memory values, and

> > -- other threads can't know that the object has been loaded
> > unless you tell them, and telling them involves system
> > requests which synchronize memory.

> In Windows if a DLL containing the definition of MySingleton
> is loaded after main() begins with a call to LoadLibrary(),
> then AFAIK MySingleton::GetInstance() will be called before
> LoadLibrary() returns because of the static initialisation.
> So the singleton is fully constructed before any attempt is
> made to bind a function call to MySingleton::GetInstance().

Attention: fully constructed isn't enough. There's also a
question of memory synchronization---are other threads
guaranteed to see the version the thread which called
LoadLibrary() sees?

Under Posix (and I'm pretty sure under Windows as well), all
thread related system requests guarantee memory synchronization,
so if you use system requests to communicate the availability of
the new service to other threads, you are safe. The same may
not be true for certain lock-free algorithms.

> > > After main() is called, threads may be created that call
> > > GetInstance(). All threads will find that the MySingleton
> > > object has already been fully constructed, even in a
> > > multiprocessor machine. Note that thread creation
> > > implicitly involves the necessary memory barriers.

> > > MySingleton can choose to use a mutex member if it is
> > > mutative. Otherwise it may provide shared read access
> > > without any mutex at all.

> > If it is mutative, and represents the correct level of
> > granularity for locking, another alternative is to acquire
> > the lock before checking for null, and to return a
> > boost::shared_ptr to the object, whose "destructor" frees
> > the lock. You need one lock anyway, this avoids a second.

> I presume I misunderstand you because it seems like you will
> have a problem accessing an uninitialised lock if the
> singleton is accessed before main() begins.

Mutexes can be initialilzed statically, at least under Posix.
And static initialization takes place before any dynamic
initialization. Alternatively, use a singleton as above to
create the mutex. (But I really can't imagine a system where
mutexes can't be initialized statically. It sounds like a real
recepe for order of initialization problems.)

--
James Kanze GABI Software
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

Matthias Hofmann

unread,
Aug 1, 2006, 5:33:57 PM8/1/06
to
"kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
news:1154432716.0...@b28g2000cwb.googlegroups.com...

> > What could happen? The only thing I can imagine is using the
> > char pointer to modify the string literal. This can be fixed
> > by using a pointer to a const char.
>
> void
> muckItUp()
> {
> char doh[] = "How long will I exist?" ;
> Singleton::GetInstance().SetName( doh ) ;
> }
>
> I wouldn't like to use the singleton after a call to muckItUp.

I see. Would it make a difference if doh' were a pointer to a char rather
than an array, as follows?

char* doh = "Am I located on the stack?";

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Aug 1, 2006, 5:34:39 PM8/1/06
to
"kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
news:1154436138....@p79g2000cwp.googlegroups.com...

> > What exactly is the problem with creation of a local static
> > object and threads?
>
> The code generated by most compilers isn't thread safe.
> Typically, there will be a hidden static bool which says whether
> the object has been initialized or not; the compiler tests this,
> and if it is false, calls the constructor, and then sets it to
> true. If no particular steps are taken by the compiler, this
> isn't thread safe.

Is this hidden static bool shared by the threads? I can imagine that there
is a problem if the bool is shared while the object is not or vice versa.
Otherwise I don't understand what could go wrong.

> [...]
> > > > Formally, there is no guarantee that static variables are
> > > > constructed before entering main, so you have no guaranteed that
> > > > your s_init object (or my ourInstance pointer) will be
> > > > initialized before entering main.
>
> > > Really! Are you referring to the C++ standard?
>
> > It is described in 3.6.2/3. If I understand this part of the
> > standard correctly, it does, however, guarantee that the
> > ourInstance pointer will be initialized before it is first
> > used.
>
> It guarantees that the pointer will be initialized before the
> first use of anything defined in the translation unit. In
> particular, it guarantees that the pointer will be initialized
> before the first call to Singleton::GetInstance().

And what if nothing is used except for the pointer itself? Strangely, I
found no text in the standard that explicitly guarantees that an object will
be initialized before it is first used... Or maybe I just overlooked it?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

David Barrett-Lennard

unread,
Aug 1, 2006, 11:16:13 PM8/1/06
to

kanze wrote:
> Earl Purple wrote:
> > David Barrett-Lennard wrote:
>
> > > ///////////// header
> > > class MySingleton
> > > {
> > > public:
> > > static MySingleton& GetInstance();
> > > private:
> > > MySingleton();
> > > };
>
> > > ////////////// cpp
> > > MySingleton& MySingleton::GetInstance()
> > > {
> > > static MySingleton s;
> > > return s;
> > > }
>
> > Is this not threadsafe anyway (assuming you have a compliant
> > compiler?). There should be only one instance of a static
> > regardless of race conditions.
>
> Should is a very vague word. According to what standard? The
> C++ standard says that as soon as you invoke pthread_create, or
> something along those lines, you have undefined behavior. And
> Posix doesn't say anything about it.
>
> >From a quality of implementation point of view, I'd say you were
> right. From a practical point of view, however, most compilers
> don't seem to guarantee that this function is thread safe.

I don't like the idea that the compiler would take upon itself the
need to insert thread-safety code. Otherwise how do you optimize for
cases where you know you don't need multi-thread protection? Also,
where does it end? Imagine if the compiler tried to protect all your
global variables as well, or made sure reading and writing double
precision floats were atomic.

Cheers,
David Barrett-Lennard

David Barrett-Lennard

unread,
Aug 1, 2006, 11:15:19 PM8/1/06
to

Francis Glassborow wrote:
> In article <1154389322.7...@b28g2000cwb.googlegroups.com>,
> David Barrett-Lennard <dav...@iinet.net.au> writes
> >I wanted a singleton that is threadsafe yet doesn't necessarily require
> >synchronisation primitives in order to access it. This is particularly
> >beneficial for immutable singletons that support shared read access.
>
> Where is the problem if it is immutable?

Consider a CRC32 algorithm that uses a look up table with 256 x 32 bit
integers. The look up table itself needs to be calculated. However
once that is done it is read only. The function that actually uses the
read only LUT doesn't want the overhead of locking or memory
barriers. This could make a *huge* difference in the performance,
particularly if there are threads calculating CRCs on relatively small
buffers.

Cheers,
David Barrett-Lennard

David Barrett-Lennard

unread,
Aug 1, 2006, 11:15:44 PM8/1/06
to

Gene Bushuyev wrote:
> "David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
> news:1154313829.5...@p79g2000cwp.googlegroups.com...
> [...]
> > The GetInstance() function employs the lazy creation approach.
> > However, the intention is not to avoid consuming resources. In fact
> > the static InitMySingleton instance is used to force the singleton to
> > be eagerly initialized before main() begins.
>
> You don't have any guarantee that either one of your objects is
> itinitialized
> before main (3.6.2/3). The standard only requires that they are
initialized
> before the first use, neither static MySingleton nor s_init are used
before
> main() in your example.

I think that's a shame. I like to be able to have code knowingly run
before main() begins. For example, to allow factories to self-register
with a singleton factory registry.

Do you know of any compilers that don't execute the s_init
constructor before main()?

Cheers,
David Barrett-Lennard

David Barrett-Lennard

unread,
Aug 2, 2006, 12:25:42 AM8/2/06
to

kanze wrote:
> David Barrett-Lennard wrote:
> > kanze wrote:
> > > David Barrett-Lennard wrote:
>
> [...]
> > > At least some compilers, in a threaded environment, use
> > > something like pthread_once to initialize the variable, so
> > > constructing it before entering main isn't necessary.
>
> > Good point. I didn't know some compilers would do that.
>
> Only some. In my opinion, it should be required, once the C++
> standard recognizes threads, but there are valid arguments both
> ways: a function with a static variable is inherently not thread
> safe, and presumably will be used only in a single threaded
> environment, or when the client code has provided higher level
> protection. In such cases, there is no threading issue in the
> code, and the use of something like pthread_once is extra
> overhead---you're paying for something you don't use. (But I'm
> still in favor of doing the right thing.)

I think the compiler should keep out of such concerns! Particularly
now that most compilers don't give thread safety. The cat's out of
the bag!

> > > At the other extreme, other compilers document nothing, and
> > > may use some technique which isn't thread safe. In the
> > > absense of any specific guarantees, I prefer to avoid
> > > counting too much on what the compiler does here.
>
> > > My own technique is basically:
>
> > > static MySingleton* ourInstance = &MySingleton::instance() ;
>
> > > MySingleton&
> > > MySingleton::instance()
> > > {
> > > if ( ourInstance == NULL ) {
> > > ourInstance = new MySingleton ;
> > > }
> > > return *ourInstance ;
> > > }
>
> > How is it deleted?
>
> It isn't. Generally, I don't want it to be; deleting it leads
> to problems in the ordering of destructors (supposing it is used
> in the destructor of an object with static lifetime).

I have never had an order of destruction problem myself. However I use
singletons rarely and they tend to be used either for caching or for
registries. Can you outline a reasonable example with order of
destruction problems?

> > In Windows if a DLL containing the definition of MySingleton
> > is loaded after main() begins with a call to LoadLibrary(),
> > then AFAIK MySingleton::GetInstance() will be called before
> > LoadLibrary() returns because of the static initialisation.
> > So the singleton is fully constructed before any attempt is
> > made to bind a function call to MySingleton::GetInstance().
>
> Attention: fully constructed isn't enough. There's also a
> question of memory synchronization---are other threads
> guaranteed to see the version the thread which called
> LoadLibrary() sees?

Unfortunately I doubt whether Microsoft documentation will say!

> Under Posix (and I'm pretty sure under Windows as well), all
> thread related system requests guarantee memory synchronization,
> so if you use system requests to communicate the availability of
> the new service to other threads, you are safe. The same may
> not be true for certain lock-free algorithms.

> > > If it is mutative, and represents the correct level of


> > > granularity for locking, another alternative is to acquire
> > > the lock before checking for null, and to return a
> > > boost::shared_ptr to the object, whose "destructor" frees
> > > the lock. You need one lock anyway, this avoids a second.
>
> > I presume I misunderstand you because it seems like you will
> > have a problem accessing an uninitialised lock if the
> > singleton is accessed before main() begins.
>
> Mutexes can be initialilzed statically, at least under Posix.
> And static initialization takes place before any dynamic
> initialization.

Note that Win32 events, mutexes, critical sections etc cannot be
initialized statically under Windows. For example, I quote from MSDN

"The process is responsible for allocating the memory used by a
critical section object, which it can do by declaring a variable of
type CRITICAL_SECTION. Before using a critical section, some thread of
the process must call the InitializeCriticalSection or
InitializeCriticalSectionAndSpinCount function to initialize the
object."

> Alternatively, use a singleton as above to
> create the mutex. (But I really can't imagine a system where
> mutexes can't be initialized statically. It sounds like a real
> recepe for order of initialization problems.)


Cheers,
David Barrett-Lennard

Gene Bushuyev

unread,
Aug 2, 2006, 8:16:10 AM8/2/06
to
"David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
news:1154486385.3...@i3g2000cwc.googlegroups.com...

>
> Gene Bushuyev wrote:
>> "David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
>> news:1154313829.5...@p79g2000cwp.googlegroups.com...
>> [...]
>> > The GetInstance() function employs the lazy creation approach.
>> > However, the intention is not to avoid consuming resources. In fact
>> > the static InitMySingleton instance is used to force the singleton to
>> > be eagerly initialized before main() begins.
>>
>> You don't have any guarantee that either one of your objects is
>> itinitialized
>> before main (3.6.2/3). The standard only requires that they are
> initialized
>> before the first use, neither static MySingleton nor s_init are used
> before
>> main() in your example.
>
> I think that's a shame. I like to be able to have code knowingly run
> before main() begins. For example, to allow factories to self-register
> with a singleton factory registry.
>
> Do you know of any compilers that don't execute the s_init
> constructor before main()?


No, that's not a shame, that's a compiler optimization :-) An aggressive
optimizing compiler may decide to throw s_init away completely to make your
program run faster, because it is never used.
The standard says that introducing a side effect in constructor forces
compiler
to initialize the objects. So your unused s_init would be initialized if its

constructor had a side effect (3.7.1/2). Definition of the side effect is
found
in (1.9/7): "Accessing an object designated by a volatile lvalue (3.10),
modifying an object, calling a library I/O function, or calling a function
that
does any of those operations are all side effects, which are changes in the
state of the execution environment..."
But don't forget that those side effects must be observable, or compiler can

disregard them following "as-if" rule.

--
Gene Bushuyev (www.gbresearch.com)
----------------------------------------------------------------
To see what is in front of one's nose needs a constant struggle ~ George
Orwell

kanze

unread,
Aug 2, 2006, 8:42:23 AM8/2/06
to
Matthias Hofmann wrote:
> "kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
> news:1154432716.0...@b28g2000cwb.googlegroups.com...

> > > What could happen? The only thing I can imagine is using
> > > the char pointer to modify the string literal. This can be
> > > fixed by using a pointer to a const char.

> > void
> > muckItUp()
> > {
> > char doh[] = "How long will I exist?" ;
> > Singleton::GetInstance().SetName( doh ) ;
> > }

> > I wouldn't like to use the singleton after a call to muckItUp.

> I see. Would it make a difference if doh' were a pointer to a
> char rather than an array, as follows?

> char* doh = "Am I located on the stack?";

Obviously. The problem is one of object lifetime; using a char
pointer, instead of std::string, only works if the object
lifetime of the char const[] it points to is static (or strictly
speaking, at least until the next call to SetName. Anytime you
pass the address of a string literal, this condition is met.

David's example is probably more realistic of what will happen
in practice. The user will create the string in an std::string,
and then use c_str() to pass it to SetName.

--
James Kanze GABI Software
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

kanze

unread,
Aug 2, 2006, 8:57:59 AM8/2/06
to

It does all the time. Luckily for us, because otherwise, we
couldn't use it in a multithreaded environment.

> Otherwise how do you optimize for cases where you know you
> don't need multi-thread protection?

A special option to the compiler?

> Also, where does it end?

Where ever the standard says it ends:-). That's the problem
here---there's no standard.

> Imagine if the compiler tried to protect all your global
> variables as well, or made sure reading and writing double
> precision floats were atomic.

Imagine if it didn't ensure that the compiler generated
temporaries were not static. Or if it didn't provide correct
locking around those that weren't---this was the case with g++
pre 3.0, and you couldn't use that compiler for code which would
run in a multithreaded environment.

Fundamentally, it is almost the same issue here. The problem is
a compiler generated bool, which you, as the user, don't have
access to. It's not quite the same thing as the static
variables involved in, say, the stack walkback of exception
handling, but there is a basic principle involved. If I write:

void
f()
{
static int const xxx = 42 ;
// ...
}

no locking is required by the user. So I would expect the same
to hold for:

void
f()
{
static std::string const xxx( "doh" ) ;
// ...
}

--
James Kanze GABI Software
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

kanze

unread,
Aug 2, 2006, 9:06:30 AM8/2/06
to
Matthias Hofmann wrote:
> "kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
> news:1154436138....@p79g2000cwp.googlegroups.com...

> > > What exactly is the problem with creation of a local static
> > > object and threads?

> > The code generated by most compilers isn't thread safe.
> > Typically, there will be a hidden static bool which says
> > whether the object has been initialized or not; the compiler
> > tests this, and if it is false, calls the constructor, and
> > then sets it to true. If no particular steps are taken by
> > the compiler, this isn't thread safe.

> Is this hidden static bool shared by the threads?

Obviously.

> I can imagine that there is a problem if the bool is shared
> while the object is not or vice versa. Otherwise I don't
> understand what could go wrong.

The fact that the initialization is not atomic. In the end, the
compiler generated code is more or less:

static bool initalized = false ;
if ( ! initialized ) {
doTheInitialization() ;
initialized = true ;
}

If another thread comes in while you are doing the
initialization, it too will do the initialization. If the
initiallization includes e.g. a constructor, you're going to
call the constructor on the object twice.

On a Posix system, the obvious solution is to do away with the
bool, and generate:
pthread_once( doTheInitialization ) ;
Of course, this becomes a bit hairy if the initiallization uses
local variables (like the function parameters). And who
guarantees that pthread_once is cheap.

> > [...]
> > > > > Formally, there is no guarantee that static variables are
> > > > > constructed before entering main, so you have no guaranteed that
> > > > > your s_init object (or my ourInstance pointer) will be
> > > > > initialized before entering main.

> > > > Really! Are you referring to the C++ standard?
> >
> > > It is described in 3.6.2/3. If I understand this part of the
> > > standard correctly, it does, however, guarantee that the
> > > ourInstance pointer will be initialized before it is first
> > > used.
> >
> > It guarantees that the pointer will be initialized before the
> > first use of anything defined in the translation unit. In
> > particular, it guarantees that the pointer will be initialized
> > before the first call to Singleton::GetInstance().

> And what if nothing is used except for the pointer itself?

The pointer is an object in the translation unit. The standard
guarantees initialization before first use of anything in the
translation unit, not just functions.

> Strangely, I found no text in the standard that explicitly
> guarantees that an object will be initialized before it is
> first used... Or maybe I just overlooked it?

No. This guarantee is explicitly not given; there are even
cases where the standard guarantees that the dynamic
initialization will NOT have taken place before the object is
used. (My solution to this problem, with:
Singleton* Singleton::ourInstance = &Singleton::instance() ;
is an example of code which counts on the function seeing the
zero initialization, before the dynamic initialization has
terminated.)

--
James Kanze GABI Software
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

kanze

unread,
Aug 2, 2006, 9:11:59 AM8/2/06
to
David Barrett-Lennard wrote:
> Gene Bushuyev wrote:
> > "David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
> > news:1154313829.5...@p79g2000cwp.googlegroups.com...
> > [...]
> > > The GetInstance() function employs the lazy creation
> > > approach. However, the intention is not to avoid
> > > consuming resources. In fact the static InitMySingleton
> > > instance is used to force the singleton to be eagerly
> > > initialized before main() begins.

> > You don't have any guarantee that either one of your objects
> > is itinitialized before main (3.6.2/3). The standard only
> > requires that they are initialized before the first use,
> > neither static MySingleton nor s_init are used before main()
> > in your example.

> I think that's a shame. I like to be able to have code
> knowingly run before main() begins. For example, to allow
> factories to self-register with a singleton factory registry.

You're not alone.

> Do you know of any compilers that don't execute the s_init
> constructor before main()?

There aren't any (supposing static linking, of course). And
there won't be, for two reasons:

1. the auto-registration idiom has become a more or less
standard idiom, enough so that no compiler vendor would risk
breaking it, and

2. if the compiler defers initialization until after main, IT
(and not the user) must solve the order of initialization
problems. Which is decidedly non trivial in the general
case, and probably impossible in cases where there are
circular dependencies (and the standard makes no exception
for circular dependencies).

So although the standard doesn't guarantee it, I depend on it,
and I'm not worried about it not working in future compilers.

--
James Kanze GABI Software
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

kanze

unread,
Aug 2, 2006, 9:12:44 AM8/2/06
to
David Barrett-Lennard wrote:
> kanze wrote:
> > David Barrett-Lennard wrote:
> > > kanze wrote:
> > > > David Barrett-Lennard wrote:

> > [...]
> > > > At least some compilers, in a threaded environment, use
> > > > something like pthread_once to initialize the variable, so
> > > > constructing it before entering main isn't necessary.

> > > Good point. I didn't know some compilers would do that.

> > Only some. In my opinion, it should be required, once the
> > C++ standard recognizes threads, but there are valid
> > arguments both ways: a function with a static variable is
> > inherently not thread safe, and presumably will be used only
> > in a single threaded environment, or when the client code
> > has provided higher level protection. In such cases, there
> > is no threading issue in the code, and the use of something
> > like pthread_once is extra overhead---you're paying for
> > something you don't use. (But I'm still in favor of doing
> > the right thing.)

> I think the compiler should keep out of such concerns!
> Particularly now that most compilers don't give thread safety.

The last compiler I used that didn't guarantee thread safety was
g++ 2.95.2. If a compiler doesn't guarantee thread safety, you
can't use it for multithreaded code. It's as simple as that.
How do you know that it doesn't use static variables internally?

If I can write:

void
f()
{
static int const i = 42 ;
// ...
}

and expect it to work, I should also be able to write:

void
f()
{
static std::string const s = "42" ;
// ...
}

Where's the logical difference?

> The cat's out of the bag!

It is already.

> > > > At the other extreme, other compilers document nothing, and
> > > > may use some technique which isn't thread safe. In the
> > > > absense of any specific guarantees, I prefer to avoid
> > > > counting too much on what the compiler does here.

> > > > My own technique is basically:

> > > > static MySingleton* ourInstance = &MySingleton::instance() ;

> > > > MySingleton&
> > > > MySingleton::instance()
> > > > {
> > > > if ( ourInstance == NULL ) {
> > > > ourInstance = new MySingleton ;
> > > > }
> > > > return *ourInstance ;
> > > > }

> > > How is it deleted?

> > It isn't. Generally, I don't want it to be; deleting it leads
> > to problems in the ordering of destructors (supposing it is used
> > in the destructor of an object with static lifetime).

> I have never had an order of destruction problem myself.

You've never had one, or you've never had one that hadn't been
solved by someone else already. Have you ever used std::cerr in
the destructor of a static object? How do you know that it
hadn't been destructed already? The standard has taken special
precautions to ensure that it will not be destructed.

> However I use singletons rarely and they tend to be used
> either for caching or for registries. Can you outline a
> reasonable example with order of destruction problems?

A singleton log? I can imagine wanting to log in a destructor.

More generally, as a matter of principle. The goal is that a
user can use a singleton at any time, without worry, and it will
be there. He's independant of order of construction issues, but
also of order of destruction.

> > > In Windows if a DLL containing the definition of MySingleton
> > > is loaded after main() begins with a call to LoadLibrary(),
> > > then AFAIK MySingleton::GetInstance() will be called before
> > > LoadLibrary() returns because of the static initialisation.
> > > So the singleton is fully constructed before any attempt is
> > > made to bind a function call to MySingleton::GetInstance().

> > Attention: fully constructed isn't enough. There's also a
> > question of memory synchronization---are other threads
> > guaranteed to see the version the thread which called
> > LoadLibrary() sees?

> Unfortunately I doubt whether Microsoft documentation will
> say!

In which case, you have to assume not. (Posix documentation
says that there is no guarantee that they will---dlopen is NOT
in the list of the functions which guarantee memory
synchronization.)

> > Under Posix (and I'm pretty sure under Windows as well), all
> > thread related system requests guarantee memory
> > synchronization, so if you use system requests to
> > communicate the availability of the new service to other
> > threads, you are safe. The same may not be true for certain
> > lock-free algorithms.

> > > > If it is mutative, and represents the correct level of
> > > > granularity for locking, another alternative is to
> > > > acquire the lock before checking for null, and to return
> > > > a boost::shared_ptr to the object, whose "destructor"
> > > > frees the lock. You need one lock anyway, this avoids a
> > > > second.

> > > I presume I misunderstand you because it seems like you
> > > will have a problem accessing an uninitialised lock if the
> > > singleton is accessed before main() begins.

> > Mutexes can be initialilzed statically, at least under
> > Posix. And static initialization takes place before any
> > dynamic initialization.

> Note that Win32 events, mutexes, critical sections etc cannot
> be initialized statically under Windows.

That's bad:-(. I guess you're stuck using a singleton for the
mutex or critical section.

> For example, I quote from MSDN

> "The process is responsible for allocating the memory used by
> a critical section object, which it can do by declaring a
> variable of type CRITICAL_SECTION. Before using a critical
> section, some thread of the process must call the
> InitializeCriticalSection or
> InitializeCriticalSectionAndSpinCount function to initialize
> the object."

Which makes it sound like CRITICAL_SECTION is a POD. So
presumably, they could have designed a static initializer for
it. (From experience, it's not too hard to design this sort of
thing so that zero initialization is sufficient. It is for the
mutexes of Solaris, for example, although I don't believe that
this is either documented nor guaranteed.) Dynamic
initialization only becomes necessary if you have need some
attributes at other than their default value.

> > Alternatively, use a singleton as above to create the mutex.
> > (But I really can't imagine a system where mutexes can't be
> > initialized statically. It sounds like a real recepe for
> > order of initialization problems.)

Yep. Sounds like Microsoft missed the boat on this one.

--
James Kanze GABI Software
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

David Barrett-Lennard

unread,
Aug 2, 2006, 10:16:04 AM8/2/06
to

That suggests it is fairly easy to change the code in my OP to ensure
s_init is initialised. Eg

static volatile int s_dummy;
static struct InitMySingleton
{
InitMySingleton() { s_dummy = 0; MySingleton::GetInstance(); }
} s_init;

To self document this, perhaps I could define a function called
DontOptimiseAway() that has observable side-effects, and simply call it
from the constructor for s_init. Can you think of something more
elegant?

I suppose the technique used to automatically self-register things with
a singleton registry will satisfy the requirements of observable
side-effects (assuming the singleton is actually accessed via main).
Eg

static struct RegisterMyFactory
{
RegisterMyFactory() { FactoryRegistry::GetInstance().Register(new
MyFactory); }
} s_reg;


Cheers,
David Barrett-Lennard

Marcin 'Qrczak' Kowalczyk

unread,
Aug 2, 2006, 10:44:13 AM8/2/06
to
Followup-To: comp.programming.threads

"kanze" <ka...@gabi-soft.fr> writes:

> On a Posix system, the obvious solution is to do away with the
> bool, and generate:
> pthread_once( doTheInitialization ) ;
> Of course, this becomes a bit hairy if the initiallization uses
> local variables (like the function parameters). And who
> guarantees that pthread_once is cheap.

I see no reason for it to be more expensive than any other custom
solution.

--
__("< Marcin Kowalczyk
\__/ qrc...@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/

Matthias Hofmann

unread,
Aug 2, 2006, 10:43:42 AM8/2/06
to
"David Barrett-Lennard" <dav...@iinet.net.au> schrieb im Newsbeitrag
news:1154488230.2...@h48g2000cwc.googlegroups.com...

> I have never had an order of destruction problem myself. However I use
> singletons rarely and they tend to be used either for caching or for
> registries. Can you outline a reasonable example with order of
> destruction problems?

I had these order of destruction problems when I used a memory tracking
mechanism to keep track of dynamic strorage allocation and dealltocation.
Here's an example that demonstrates the problem:

// Begin example code
#include <iostream>

template <class T>
class A
{
T* m_ptr;

A() : m_ptr( 0 ) {}
~A() { if ( m_ptr != 0 )
std::cout << "Oops..." << std::endl; }

A( const A& ){}
A& operator=( const A& );

public:
static A& Instance()
{ static A inst; return inst; }

void HoldAddress( T* ptr )
{ m_ptr = ptr; }

void ReleaseAddress()
{ m_ptr = 0; }
};

template <class T>
class B
{
T* m_ptr;

public:
B() : m_ptr( 0 ) {}

~B(){ A<T>::Instance().ReleaseAddress();
delete m_ptr; }

void CreateTrouble()
{ m_ptr = new T;
A<T>::Instance().HoldAddress( m_ptr ); }
};

B<int> b;

int main()
{
b.CreateTrouble();

return 0;
}
// End example code

The example defines to classes named A and B. It's maybe a little easier to
understand if you imagine that in a real program, class A would hold
pointers to allocated storage.

There is one non-local static object of type B<int>, named b. It will be
created first because it is the only non-local static object in the program,
and it is the first object to be used in main(). The call to
B<int>::CreateTrouble() causes the allocation of an int and the construction
of an object of type A<int>. It passes the address of the allocated int to
A<int>::HoldAddress(), which in practice would mean keeping track of
allocated memory.

As objects of static storage duration are destroyed in the reverse order of
the completion of their constructor (see 3.6.3/1), the object of type A<int>
will be destroyed first, causing its destructor to be called. Unfortunately,
the pointer that has been passed to A<int>HoldAddress() has not been removed
from the "database" yet. This is done when the object of type B<int> is
destroyed. Note that B<int>::~B() yields undefined behaviour according to
3.6.3/2, as it calls A<int>::Instance(), which is a function containing a
local static object that has been destroyed.

The problem would not occur if B<T>::CreateTrouble() would be called from
B<T>::B(), because then, the constructor of A<T> would be completed *before*
the constructor of B<T>, causing the object of type B<int> to be destroyed
*before* the object of type A<int>. The pointer that has been passed to
A<int>::HoldAddress() would then be removed before A<int> is destroyed.

I hope I was able to explain things in an understandable way... ;-)

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Aug 2, 2006, 11:36:12 AM8/2/06
to
"kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
news:1154513036....@h48g2000cwc.googlegroups.com...

> Fundamentally, it is almost the same issue here. The problem is
> a compiler generated bool, which you, as the user, don't have
> access to. It's not quite the same thing as the static
> variables involved in, say, the stack walkback of exception
> handling, but there is a basic principle involved. If I write:
>
> void
> f()
> {
> static int const xxx = 42 ;
> // ...
> }
>
> no locking is required by the user. So I would expect the same
> to hold for:
>
> void
> f()
> {
> static std::string const xxx( "doh" ) ;
> // ...
> }
>
> --

Where is the difference between these two functions with regards to
multithreading?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Aug 2, 2006, 11:40:30 AM8/2/06
to
"kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
news:1154513641.3...@h48g2000cwc.googlegroups.com...

> > Strangely, I found no text in the standard that explicitly
> > guarantees that an object will be initialized before it is
> > first used... Or maybe I just overlooked it?
>
> No. This guarantee is explicitly not given; there are even
> cases where the standard guarantees that the dynamic
> initialization will NOT have taken place before the object is
> used. (My solution to this problem, with:
> Singleton* Singleton::ourInstance = &Singleton::instance() ;
> is an example of code which counts on the function seeing the
> zero initialization, before the dynamic initialization has
> terminated.)

You mean, you are checking for a null pointer whereever
Singleton::ourInstance is used?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Gene Bushuyev

unread,
Aug 2, 2006, 1:44:44 PM8/2/06
to
"David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
news:1154525824.3...@m73g2000cwd.googlegroups.com...
[...]

> That suggests it is fairly easy to change the code in my OP to ensure
> s_init is initialised. Eg
>
> static volatile int s_dummy;
> static struct InitMySingleton
> {
> InitMySingleton() { s_dummy = 0; MySingleton::GetInstance(); }
> } s_init;


That won't fool a good compiler :-) Now you have s_dummy that is not used,
so
the program doesn't have an observable side effect in InitMySingleton.
Therefore, following as-if rule compiler can still throw the whole thing
away. I
suggest you play with VC8 and look at the assembly, it used to be pretty
smart
removing the dead code.

--
Gene Bushuyev (www.gbresearch.com)
----------------------------------------------------------------
To see what is in front of one's nose needs a constant struggle ~ George
Orwell

Chris Thomasson

unread,
Aug 2, 2006, 4:35:50 PM8/2/06
to
"Marcin 'Qrczak' Kowalczyk" <qrc...@knm.org.pl> wrote in message
news:87psfle...@qrnik.zagroda...
> Followup-To: comp.programming.threads

>
> "Chris Thomasson" <cri...@comcast.net> writes:
>
>> The actual pattern itself it perfectly fine IMO, and can be successfully
>> implemented with assembly language and externally assembled into a
>> library
>
>> with a coherent ABI and portable C interface; no doubt about it... IMHO,
>> most of the problems that are generally associated with double checked
>> locking seem to be related to compiler reordering, and of course, the
>> "apparent" widespread lack of knowledge wrt memory barrier
> functionality...
>
> In the case of GCC external assembly should not be necessary. Appropriate
> annotations of assembler snippets (about clobbering memory, or volatile
> which prevents optimizing it out) are enough.
>
> If you claim they are not enough, please show an example.

It has been my experience that adding __volatile and "memory" decorations to
GCC inline assembly statements seem to work just fine; I really don't
remember having to actually disassemble any lock-free code on GCC...
However, you might want to take the following into account:


http://groups.google.com/group/comp.programming.threads/browse_frm/thread/7d398d017c68de53/433dcb152bd7697c?lnk=gst&q=%22alexander+terekhov%22+%2B+%22asm%22&rnum=9#433dcb152bd7697c
(read all, and follow links...)


I tend to stay away from inline assembly. I find the syntax to be tedious; I
feel out of place, so to speak... I would much rather code in "pure"
assembly... FWIW and IIRC, I heard something about Microsoft compilers
dropping inline assembly in future versions... Has anybody else heard
anything similar/else about this? Luckily for me, I don't really have to
worry about this...

;)


Chris Thomasson

unread,
Aug 2, 2006, 10:58:37 PM8/2/06
to

;)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

David Barrett-Lennard

unread,
Aug 2, 2006, 11:19:10 PM8/2/06
to

Gene Bushuyev wrote:
> "David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
> news:1154525824.3...@m73g2000cwd.googlegroups.com...
> [...]
> > That suggests it is fairly easy to change the code in my OP to ensure
> > s_init is initialised. Eg
> >
> > static volatile int s_dummy;
> > static struct InitMySingleton
> > {
> > InitMySingleton() { s_dummy = 0; MySingleton::GetInstance(); }
> > } s_init;
>
>
> That won't fool a good compiler :-) Now you have s_dummy that is not used,
> so
> the program doesn't have an observable side effect in InitMySingleton.
> Therefore, following as-if rule compiler can still throw the whole thing
> away.

I was going by your brief summary from the C++ standard. Anyway,
according to James the issue seems rather academic. Do you agree?

> I
> suggest you play with VC8 and look at the assembly, it used to be pretty
> smart
> removing the dead code.

Used to be? :)


Cheers,
David Barrett-Lennard

David Barrett-Lennard

unread,
Aug 2, 2006, 11:18:37 PM8/2/06
to

My response to James is relevant here. IMO there are a small number of
singletons (such as your class A, or his log example) that need to
outlive the scope of main() because they represent debugging aids.

If you think in terms of functional contracts that are nested within
the scope of main() then you see that most singletons won't do
anything important in their destructors and the order of destruction
problem doesn't arise.

For example I would be suspicious of a program that used singleton
destructors to close windows or sockets.

Cheers,
David Barrett-Lennard

David Barrett-Lennard

unread,
Aug 2, 2006, 11:16:06 PM8/2/06
to

AFAIK VC++ never (silently) adds synchronization primitives to your
code.

Can you give me an example of where a compiler introduces an unexpected
static?

> If I can write:
>
> void
> f()
> {
> static int const i = 42 ;
> // ...
> }
>
> and expect it to work

Why expect that to be threadsafe? The compiler isn't required to
optimize the variable out of existence is it? Assuming it initializes
it on first access, you should expect a potential racing condition.
Furthermore, even if you ensure one thread calls f() before any other
threads, you will need to ensure memory barriers are used
appropriately.

As I see it, global variables or static variables inside functions
*always* indicate potential thread-safety problems, and I don't
expect the compiler to do anything about that. This keeps the compiler
and language simple, and makes it easier to maximize performance.

> I should also be able to write:
>
> void
> f()
> {
> static std::string const s = "42" ;
> // ...
> }
>
> Where's the logical difference?
>
> > The cat's out of the bag!
>
> It is already.

> > > > > My own technique is basically:


>
> > > > > static MySingleton* ourInstance = &MySingleton::instance() ;
>
> > > > > MySingleton&
> > > > > MySingleton::instance()
> > > > > {
> > > > > if ( ourInstance == NULL ) {
> > > > > ourInstance = new MySingleton ;
> > > > > }
> > > > > return *ourInstance ;
> > > > > }
>
> > > > How is it deleted?
>
> > > It isn't. Generally, I don't want it to be; deleting it leads
> > > to problems in the ordering of destructors (supposing it is used
> > > in the destructor of an object with static lifetime).
>
> > I have never had an order of destruction problem myself.
>
> You've never had one, or you've never had one that hadn't been
> solved by someone else already. Have you ever used std::cerr in
> the destructor of a static object? How do you know that it
> hadn't been destructed already? The standard has taken special
> precautions to ensure that it will not be destructed.
>
> > However I use singletons rarely and they tend to be used
> > either for caching or for registries. Can you outline a
> > reasonable example with order of destruction problems?
>
> A singleton log? I can imagine wanting to log in a destructor.

But your singleton destructors never run!

As a general rule my programs only do observable things within the
scope of main(). Threads, files, sockets, windows etc are only opened
and closed within the scope of main(). Therefore I don't do anything
important in singleton destructors. You evidently don't either
because you don't destruct them at all.

I use assertions to trap attempts to log messages after the log file
has been explicitly closed from main(), unless the log file is a
debugging aid for the programmer. In the latter case it logically
needs to outlive the scope of main(). Only in that case would I
consider allowing the singleton to leak and assume the system closes
the log file for me.

I find it convenient to know that my programs (should) never have any
memory leaks. VC++ can dump all the leaks in the output pane. It's
nice for this to be empty unless there is a programming error.


Cheers,
David Barrett-Lennard

Gene Bushuyev

unread,
Aug 3, 2006, 8:13:57 AM8/3/06
to
"David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
news:1154573901.0...@75g2000cwc.googlegroups.com...
[...]

>
> I was going by your brief summary from the C++ standard. Anyway,
> according to James the issue seems rather academic. Do you agree?

I don't have any statistical data about modern compilers nor I have a crystall
ball to tell about future compilers. The better the optimization the more
chances that compiler will remove the dead code. Whether modern compilers
aggressively remove dead code or not I don't know, though I hope they do. It's
very difficult to test, you need to examine the assembly to find out. Otherwise
if you try debugging it, compiler will perform initialization before you can
test it. If you introduce a side effect (e.g. printing), then compiler will
perform initialization, but in production code it will remove all that stuff.
This is the case when testing changes the outcome. This of course, is not a
problem, because the program cannot detect and doesn't care if unused objects
without side effects were ever initialized. Threading issues are not side
effects, standard doesn't know anything about them.

--
Gene Bushuyev (www.gbresearch.com)
----------------------------------------------------------------
To see what is in front of one's nose needs a constant struggle ~ George Orwell

d...@pixar.com

unread,
Aug 5, 2006, 3:14:10 PM8/5/06
to
kanze wrote:
> > > Do you know of any compilers that don't execute the s_init
> > constructor before main()?
>
> There aren't any (supposing static linking, of course). And
> there won't be, for two reasons:
>
> 1. the auto-registration idiom has become a more or less
> standard idiom, enough so that no compiler vendor would risk
> breaking it, and

I can understand why you'd think this; let me just say... "Apple."

Yes, Apple had an implementation that came the closest ever to
supporting the (impossible to achieve) C++ standard concerning
initialization. (I.e. the code really didn't run constructors until
you accessed the first symbol in a translation unit). So constructors
would run for global objects, but it might be a long long long time
after main() had begun. And if you dlopen'd a library, the
constructors in the library might themselves not run until you tickled
the right bit of code inside the library. This broke auto-registration
completely. In their defense, Apple kept saying "but our
implementation follows the C++ spec --- isn't that what you hard-core
C++ programmers want to see?"

The real problem with their implementation, curiously enough, was that
while in the middle of executing a function, the code could actually
jump to running a constructor for a global object, and then return back
the original function. Unfortunately, in the presence of non-recursive
mutexes, this would quite easily deadlock their -- or your -- code.

[Note that all of this was in 10.3 and earlier. After enduring several
years of complaints, Apple backed away from their amazingly clever
implementation and now do what everybody else does. Almost a pity, as
we learned to live completely without the auto-registration pattern,
and our life is the better for it, in fact. And it was grand to see
someone go after the "pie-in-the-sky" specification.]

David Barrett-Lennard

unread,
Aug 6, 2006, 2:39:39 PM8/6/06
to

What do you think is bad about the auto-registration pattern?

>And it was grand to see
> someone go after the "pie-in-the-sky" specification.]

Cheers,
David Barrett-Lennard

Liviu

unread,
Aug 6, 2006, 2:47:12 PM8/6/06
to
Matthias Hofmann wrote:
> "kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
> news:1154513036....@h48g2000cwc.googlegroups.com...
>
> > Fundamentally, it is almost the same issue here. The problem is
> > a compiler generated bool, which you, as the user, don't have
> > access to. It's not quite the same thing as the static
> > variables involved in, say, the stack walkback of exception
> > handling, but there is a basic principle involved. If I write:
> >
> > void
> > f()
> > {
> > static int const xxx = 42 ;
> > // ...
> > }
> >
> > no locking is required by the user. So I would expect the same
> > to hold for:
> >
> > void
> > f()
> > {
> > static std::string const xxx( "doh" ) ;
> > // ...
> > }
> >
> > --
>
> Where is the difference between these two functions with regards to
> multithreading?

The former represents an object with static storage duration,
statically initialized with a constant - see 3.6.2 p1. The latter may
require dynamic initialization depending on the implementation - see
3.6.2.

HTH,
Liviu

Liviu

unread,
Aug 6, 2006, 2:45:04 PM8/6/06
to
kanze wrote:
> David Barrett-Lennard wrote:
> > I think that's a shame. I like to be able to have code
> > knowingly run before main() begins. For example, to allow
> > factories to self-register with a singleton factory registry.
>
> You're not alone.

As a person who deals with legacy code which relies on this kind of
behaviour (not mandated by the standard as previously pointed out) I
must tell you that it can very quickly become a mess from pov of both
implementation and usage. There are more robust techniques which can
accomplish the same goal.

>
> > Do you know of any compilers that don't execute the s_init
> > constructor before main()?
>
> There aren't any (supposing static linking, of course). And
> there won't be, for two reasons:

If the namespace scope objects have dynamic initialization then their
initialization falls under 3.6.2 p3. Such a code will not be portable
since it relies on implementation-defined behaviour.

The class code discussed is as simple as an example need be but in
general it is safe to assume a singleton will acquire some resource and
the implementation will require dynamic initialization, therefore will
be subject to 3.6.2 p3.

HTH,
Liviu

Liviu

unread,
Aug 6, 2006, 2:46:20 PM8/6/06
to
Gene Bushuyev wrote:
> "David Barrett-Lennard" <dav...@iinet.net.au> wrote in message
> news:1154573901.0...@75g2000cwc.googlegroups.com...
> [...]
> >
> > I was going by your brief summary from the C++ standard. Anyway,
> > according to James the issue seems rather academic. Do you agree?
>
> I don't have any statistical data about modern compilers nor I have a crystall
> ball to tell about future compilers. The better the optimization the more
> chances that compiler will remove the dead code. Whether modern compilers
> aggressively remove dead code or not I don't know, though I hope they do.

In my experience I have found out Visual Age for C++ having by far the
most aggressive optimizer out there. Tricks like the one presented
earlier with mutating volatile variables will not pass.

HTH,
Liviu

david...@gmail.com

unread,
Aug 7, 2006, 3:43:13 AM8/7/06
to
David Barrett-Lennard wrote:
> What do you think is bad about the auto-registration pattern?

Auto-registration is often (perhaps even typically) used for
registries. Imagine a program with 2 registries, A and B, with
registry A depending on registry B. That is, auto-registration that
pushes information into registry A actually queries registry B, and
you'll get the wrong result if all the auto-registrations for B haven't
yet fired.

This is a very common scenario, and it makes auto-registration fragile
-- there is no way, in general, to guarantee that all of the
auto-registrations for B will be done before all the auto-registrations
for A. (This is an obvious statement -- that you can't hurry up the
auto-registrations to B by calling them when you need them: the whole
reason you use auto-registration is because it avoids having to
centralize all the knowledge in the first place --- your information
lives in scattered global objects amongst all your libraries that
nobody really knows about until the constructor is run, and since you
don't know what's out there, you can't just call on the functions to
make them run!)

Further, "you can't call this function before main()" is a virus -- if
function F1() can't be safely called before main() because it depends
on some global constructor to run, then any function that calls F1() is
itself infected by the virus, and so on.

For this reason, dynamic initialization (at global scope) is basically
something we avoid like the plague. Even something as simple as

const std::string someGlobalString("blah"); // at file-scope

void F() {
// makes use of someGlobalString
}

can kill you, because now F() is a function that can't be (safely) run
before main.
(Yes, I know the standard says we've got to initialize someGlobalString
before we can call F(), but of course this is impossible to guarantee
-- we could have called F() from outside this file, due to some other
global constructor, before we started the constructors in this
translation unit.)

And the kicker is, just what global constructor that required calling
F() before main? Why, it was a constructor involved in
auto-registration, of course...

David Barrett-Lennard

unread,
Aug 7, 2006, 8:33:28 AM8/7/06
to

david...@gmail.com wrote:
> David Barrett-Lennard wrote:
> > What do you think is bad about the auto-registration pattern?
>
> Auto-registration is often (perhaps even typically) used for
> registries.

Not surprisingly :)

> Imagine a program with 2 registries, A and B, with
> registry A depending on registry B. That is, auto-registration that
> pushes information into registry A actually queries registry B, and
> you'll get the wrong result if all the auto-registrations for B haven't
> yet fired.
>
> This is a very common scenario

Not for me. Can you give a realistic example?

The registries for which I use auto-registration are always completely
passive in nature, and therefore don't have dependencies.

I can see the potential dangers, but in my designs registries do
nothing more that store what's been registered in them, and therefore
it's trivial to *prove* that auto-registration is well behaved.

Cheers,
David Barrett-Lennard

Eisenbart

unread,
Aug 9, 2006, 8:39:36 AM8/9/06
to
<david...@gmail.com> schrieb im Newsbeitrag
news:1154923025.1...@75g2000cwc.googlegroups.com...

> For this reason, dynamic initialization (at global scope) is basically
> something we avoid like the plague. Even something as simple as
>
> const std::string someGlobalString("blah"); // at file-scope
>
> void F() {
> // makes use of someGlobalString
> }
>
> can kill you, because now F() is a function that can't be (safely) run
> before main.
> (Yes, I know the standard says we've got to initialize someGlobalString
> before we can call F(), but of course this is impossible to guarantee
> -- we could have called F() from outside this file, due to some other
> global constructor, before we started the constructors in this
> translation unit.)

The way I understand things, it is not even safe to call F() from
inside main() unless someGlobalString has been defined in the same
translation unit as F() (see 3.6.2/3).

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

kanze

unread,
Aug 16, 2006, 6:16:11 PM8/16/06
to
Liviu wrote:
> kanze wrote:
> > David Barrett-Lennard wrote:
> > > I think that's a shame. I like to be able to have code
> > > knowingly run before main() begins. For example, to allow
> > > factories to self-register with a singleton factory
> > > registry.

> > You're not alone.

> As a person who deals with legacy code which relies on this
> kind of behaviour (not mandated by the standard as previously
> pointed out) I must tell you that it can very quickly become a
> mess from pov of both implementation and usage. There are more
> robust techniques which can accomplish the same goal.

Such as? I know a few work-arounds, but they generally involve
automatically generating code and tampering with the rules in
the makefile. And while that doesn't bother me, I know a lot of
C++ programmers who don't feel as comfortable as I do writing
and maintaining makefiles.

> > > Do you know of any compilers that don't execute the s_init
> > > constructor before main()?

> > There aren't any (supposing static linking, of course). And
> > there won't be, for two reasons:

> If the namespace scope objects have dynamic initialization
> then their initialization falls under 3.6.2 p3. Such a code
> will not be portable since it relies on implementation-defined
> behaviour.

It has been pointed out that Apple once had a compiler which
tried to take advantage of this paragraph. I've not used that
compiler, so I cannot say, but I know how to write conforming
code which wouldn't work for all of the implementations I'm
aware of---the standard makes no exception for circular
dependencies, and it is very easy to create cases where the
standard requires the initialization of module A to run before
that in module B, and vice versa.

> The class code discussed is as simple as an example need be
> but in general it is safe to assume a singleton will acquire
> some resource and the implementation will require dynamic
> initialization, therefore will be subject to 3.6.2 p3.

Certainly. But it's also quite simple to create standard
conforming code which will fail if the implementation does not
initialize before main. Such code probably doesn't occur often,
if ever, in real applications, but the standard requires that
such artificially constructed programs work, too. And when the
standard starts requiring that the initialization of variable a
run before that of variable b, AND that the initialization of
variable b run before that of a, there's not much an
implementation can do what will be conform.

--
James Kanze GABI Software
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

kanze

unread,
Aug 16, 2006, 6:15:32 PM8/16/06
to
David Barrett-Lennard wrote:
> kanze wrote:
> > David Barrett-Lennard wrote:

> > > I think the compiler should keep out of such concerns!
> > > Particularly now that most compilers don't give thread
> > > safety.

> > The last compiler I used that didn't guarantee thread safety
> > was g++ 2.95.2. If a compiler doesn't guarantee thread
> > safety, you can't use it for multithreaded code. It's as
> > simple as that. How do you know that it doesn't use static
> > variables internally?

> AFAIK VC++ never (silently) adds synchronization primitives to
> your code.

I wouldn't know. I don't know what threading guarantees it
gives.

> Can you give me an example of where a compiler introduces an
> unexpected static?

Plenty. On the old 8080, almost any time the compiler spilled
registers; indirection to the stack was so expensive that one
compiler I used allocated all local variables statically, added
a counter to detect recursion, and only copied the local
variables to the stack when you actually recursed. It's not
inconceivable that some modern compilers do this as well, for
some strange architectures.

In the case of g++ pre-3.0, the compiler used static variables
in its implementation of stack walkback, at least on a Sparc.
Two threads throw an exception at the same time, and strange
things happened.

In general, unless the compiler makes some formal guarantee, you
can't count on it working.

> > If I can write:

> > void
> > f()
> > {
> > static int const i = 42 ;
> > // ...
> > }

> > and expect it to work

> Why expect that to be threadsafe?

Because Posix requires it in C. It's hard to imagine an
implementation which would make this thread safe in C, but not
in C++.

In practice, the requirements of the C++ standard pretty much
mean that a non-thread-safe implementation is not possible.
§3.6.2/1: "Objects of POD types with static storage duration
initialized with constant expressions shall be initialized
before any dynamic initialization takes place." Theoretically,
I guess you could arrange for pthread_create to be called before
any dynamic initialization takes place, but practically, the
compiler can't recognize the case if you, and even if it could,
it wouldn't go to the bother of generating special code just to
break your program. (In all implementations I'm aware of, i is
initialized as part of loading the image from disk, before any
user code, or even the compiler's own startup code has had a
chance to run.)

> The compiler isn't required to optimize the variable out of
> existence is it? Assuming it initializes it on first access,
> you should expect a potential racing condition.

But the C++ standard doesn't allow it to wait until first access
to initialize it. (Except, I guess, under the "as if" rule.
There's no way you could see the value in a conforming program
before calling f. But in practice, it doesn't happen.)

> Furthermore, even if you ensure one thread calls f() before
> any other threads, you will need to ensure memory barriers are
> used appropriately.

Both pthread_create and its equivalent in Windows take care of
that.

[...]


> > > However I use singletons rarely and they tend to be used
> > > either for caching or for registries. Can you outline a
> > > reasonable example with order of destruction problems?

> > A singleton log? I can imagine wanting to log in a destructor.

> But your singleton destructors never run!

Right. Which is exactly what I want.

> As a general rule my programs only do observable things within
> the scope of main(). Threads, files, sockets, windows etc are
> only opened and closed within the scope of main(). Therefore
> I don't do anything important in singleton destructors. You
> evidently don't either because you don't destruct them at all.

In the case of my singleton log, I would do something important
in the destructor if I called it. Something I don't want to do
before the last user written code has run. (And something that
isn't necessary to do, since the system will take care of any
necessary clean-up: close the file, free the memory, etc.)
Conceptually, it might be cleaner to say somehow that running
this destructor must be the very last thing you do, but neither
C++ nor any of the implementations I know have anything to
support this. And in practice, letting the system do it works
just as well.

> I use assertions to trap attempts to log messages after the
> log file has been explicitly closed from main(), unless the
> log file is a debugging aid for the programmer.

Which is almost always the case.

> In the latter case it logically needs to outlive the scope of
> main(). Only in that case would I consider allowing the
> singleton to leak and assume the system closes the log file
> for me.

> I find it convenient to know that my programs (should) never
> have any memory leaks. VC++ can dump all the leaks in the
> output pane. It's nice for this to be empty unless there is a
> programming error.

Well, the memory checker I use (Purify) will not display a
positive memory leak if there is a pointer to the object in
static memory. It will indicate a "potential memory leak", but
even that can be masked out (on a one by one basis, or
globally).

The crufty, hand-built checker I use at home also allows masking
out allocations in the creation of such never-to-be destructed
objects, although in this case, you do have to modify the code,
to tell the checker that it shouldn't check allocations in this
particular span of code; it does so by constructing a special
object on the stack, and it would be fairly simple to provide a
dummy object for the cases where the memory checker wasn't
linked in.

If you're memory checker doesn't have support for this sort of
thing, I'd suggest you get something better.

--
James Kanze GABI Software
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

kanze

unread,
Aug 16, 2006, 6:14:50 PM8/16/06
to
Matthias Hofmann wrote:
> "kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
> news:1154513036....@h48g2000cwc.googlegroups.com...

> > Fundamentally, it is almost the same issue here. The
> > problem is a compiler generated bool, which you, as the
> > user, don't have access to. It's not quite the same thing
> > as the static variables involved in, say, the stack walkback
> > of exception handling, but there is a basic principle
> > involved. If I write:

> > void
> > f()
> > {
> > static int const xxx = 42 ;
> > // ...
> > }

> > no locking is required by the user. So I would expect the
> > same to hold for:

> > void
> > f()
> > {
> > static std::string const xxx( "doh" ) ;
> > // ...
> > }

> Where is the difference between these two functions with
> regards to multithreading?

The first has static initialization, which occurs before program
execution begins (and thus before any thread can have been
started). In actual practice, on all of the systems I know, the
compiler will reserve 4 bytes for the int in the data segment,
and put the 42 in the corresponding 4 bytes of the executable;
"initialization" occurs when the process image is loaded from
disk. (Supposing you take the address of xxx, or do something
else which requires the actual variable to exist. Otherwise, of
course, the compiler just uses 42, without worrying about it.)

The second is dynamic initialization, which a non-trivial
constructor. The constructor will be called anytime execution
flow arrives at the statement, and the object is not already
constructed. As far as I know, there are only one technique
used to do this: an additional static bool variable which is set
after returning from the constructor. (Note that if the
constructor terminates because of an exception, the object is
not yet initialized, and the constructor will be called again
the next time the function is called.)

Of course, if a second thread enters the function while you are
executing the constructor of xxx...

--
James Kanze GABI Software
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

Liviu

unread,
Aug 17, 2006, 3:05:41 PM8/17/06
to
kanze wrote:
> Liviu wrote:
> > kanze wrote:
> > > David Barrett-Lennard wrote:
> > > > I think that's a shame. I like to be able to have code
> > > > [...]

>
> > > You're not alone.
>
> > As a person who deals with legacy code which relies on this
> > kind of behaviour (not mandated by the standard as previously
> > pointed out) I must tell you that it can very quickly become a
> > mess from pov of both implementation and usage. There are more
> > robust techniques which can accomplish the same goal.
>
> Such as? [...]

This could easily become a thread in its own. One possible solution to
the registry problem would be to use POSIX pthread_once. The
pthread_once_t variables can be initialized statically and, if in the
same translation unit as the registry access functions - could be
robustly used to conditionally initialize the registry (once) in an MT
environ. (Unfortunately, I don't think there is any way to robustly
package that type and that POSIX function into a C++ class type...)

>
> > > > Do you know of any compilers that don't execute the s_init
> > > > constructor before main()?
> > > There aren't any (supposing static linking, of course). And
> > > there won't be, for two reasons:
> > If the namespace scope objects have dynamic initialization
> > then their initialization falls under 3.6.2 p3. Such a code
> > will not be portable since it relies on implementation-defined
> > behaviour.
>
> It has been pointed out that Apple once had a compiler which
> tried to take advantage of this paragraph. I've not used that
> compiler, so I cannot say, but I know how to write conforming
> code which wouldn't work for all of the implementations I'm
> aware of---the standard makes no exception for circular
> dependencies, and it is very easy to create cases where the
> standard requires the initialization of module A to run before
> that in module B, and vice versa.

Hehe. Yes, following the standard does not give one the warranty of a
clean ride but not following the standard will most certainly get you
in trouble sooner or later.

I would rather have a compiler follow the standard to the letter than
have the compiler implementors attempt to make my life "easy". Easy
costs later - or so it has been in my experience (of C++ library
porting/maintenance).

- L

kanze

unread,
Aug 18, 2006, 1:48:02 PM8/18/06
to
Liviu wrote:
> kanze wrote:
> > Liviu wrote:
> > > kanze wrote:
> > > > David Barrett-Lennard wrote:
> > > > > I think that's a shame. I like to be able to have code
> > > > > [...]

> > > > You're not alone.

> > > As a person who deals with legacy code which relies on this
> > > kind of behaviour (not mandated by the standard as previously
> > > pointed out) I must tell you that it can very quickly become a
> > > mess from pov of both implementation and usage. There are more
> > > robust techniques which can accomplish the same goal.

> > Such as? [...]

> This could easily become a thread in its own. One possible
> solution to the registry problem would be to use POSIX
> pthread_once. The pthread_once_t variables can be initialized
> statically and, if in the same translation unit as the
> registry access functions - could be robustly used to
> conditionally initialize the registry (once) in an MT environ.
> (Unfortunately, I don't think there is any way to robustly
> package that type and that POSIX function into a C++ class
> type...)

Attention: pthread_once and exceptions don't mix well. And
registration can almost always trigger an exception, so can't be
done from pthread_once. (And of course, pthread_once isn't
present on Windows based systems. And boost::once explicitly
says that the called function may not throw.)

But I don't see where your approach solves anything. The
problem is to avoid having to list the objects to be registered
in any one C++ file. This may be a false problem in many
cases---I still have to list them somewhere, for example, in the
makefile, and it's pretty simple to write a makefile that uses
this list to generate the required C++ file. In other cases,
however... I've use the technique when configuring different
versions of a program, by linking in more or less different
modules. I've even used it for dynamically linked modules, some
of which weren't known when the program was built.

It's obviously possible to do away with automatic construction
of static variables completely, and just call an init function
for each module from main. This is the sort of thing dynamic
initialization of static variables was designed to do away with.

[...]


> Hehe. Yes, following the standard does not give one the
> warranty of a clean ride but not following the standard will
> most certainly get you in trouble sooner or later.

Not always. It depends on what you are doing, and what your
portability goals are. As soon as you include <unistd.h>,
you're not following the C++ standard, but I do it all the time.
Anytime you convert a value read with istream::get() (or
fgetc()) to a char, you're risking undefined behavior. But
idioms along the lines of:

for ( int ch = source.get() ;
ch != EOF /* && something */ ;
ch = source.get()) {
someString.push_back( ch ) ;
}

are so common that I take the risk, considering that no compiler
would dare break it.

--
James Kanze GABI Software
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

0 new messages