 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
glenlow@pixelglow.com Guest
|
Posted: Wed Dec 15, 2004 6:51 pm Post subject: Emulating a static constructor |
|
|
There's a feature I quite like in Java and C# called a "static
constructor". It's just code tied to an object that you want to execute
before the first instance of the object is created. This can be useful
to do complicated initialization of static data members, and sometimes
you don't want to do this when the first instance is created -- e.g. to
avoid synchronizing such code in the face of multiple threads and/or
you're writing a library and don't want the client to have to
explicitly initialize the package.
Do you think this is a suitable emulation?
class T
{
static int static_constructor () { ...; return 0; }
static int dummy;
}
int T::dummy = static_constructor ();
OR, in the template case:
template <typename U> class T
{
static int static_constructor () { ...; return 0; }
static int dummy;
}
template <typename U> int T <U>::dummy = static_constructor ();
If I read the Standard correctly, the dummy is dynamically initialized
at namespace scope. While it is unspecified whether it runs before the
first statement of main (3.6.2/3), it must be done before the first use
of any function from that translation unit, which presumably includes
constructing objects of type T. A multithreading-aware compiler should
ensure that this happens before any threads create the objects.
Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Stephen Howe Guest
|
Posted: Thu Dec 16, 2004 1:31 pm Post subject: Re: Emulating a static constructor |
|
|
| Quote: | There's a feature I quite like in Java and C# called a "static
constructor". It's just code tied to an object that you want to execute
before the first instance of the object is created. This can be useful
to do complicated initialization of static data members, and sometimes
you don't want to do this when the first instance is created -- e.g. to
avoid synchronizing such code in the face of multiple threads and/or
you're writing a library and don't want the client to have to
explicitly initialize the package.
|
I think you might be interested in "Schwarz counters".
They avoid clients specifically having to initalise packages and I think
could be made thread proof.
Have a look here and page down
http://www-d0.fnal.gov/KAI/doc/tutorials/static_initialization.html
Stephen Howe
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
clemd@acm.org Guest
|
Posted: Thu Dec 16, 2004 1:33 pm Post subject: Re: Emulating a static constructor |
|
|
[email]glenlow (AT) pixelglow (DOT) com[/email] wrote:
| Quote: | There's a feature I quite like in Java and C# called a "static
constructor".
|
You could also have the initialization of a static local variable (i in
this example) call the static constructor:
classs C
{
static void init() { // every constructor of C must call init()
static int i = static_constructor();
}
static int static_constructor() { ... ; return 0; }
public:
C() { init(); } // must call init()
};
It's a bit more work in each constructor, but the static constructor
will be called only if an object is created.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Thu Dec 16, 2004 1:40 pm Post subject: Re: Emulating a static constructor |
|
|
[email]glenlow (AT) pixelglow (DOT) com[/email] wrote:
| Quote: | There's a feature I quite like in Java and C# called a "static
constructor". It's just code tied to an object that you want to execute
before the first instance of the object is created. This can be useful
to do complicated initialization of static data members, and sometimes
you don't want to do this when the first instance is created -- e.g. to
avoid synchronizing such code in the face of multiple threads and/or
you're writing a library and don't want the client to have to
explicitly initialize the package.
Do you think this is a suitable emulation?
|
No.
| Quote: | class T
{
static int static_constructor () { ...; return 0; }
static int dummy;
}
int T::dummy = static_constructor ();
OR, in the template case:
template <typename U> class T
{
static int static_constructor () { ...; return 0; }
static int dummy;
}
template <typename U> int T <U>::dummy = static_constructor ();
If I read the Standard correctly, the dummy is dynamically initialized
at namespace scope. While it is unspecified whether it runs before the
first statement of main (3.6.2/3), it must be done before the first use
of any function from that translation unit, which presumably includes
constructing objects of type T. A multithreading-aware compiler should
ensure that this happens before any threads create the objects.
|
How? And, yes, in a multi-translation-unit program, I can simply create
an object of 'T' or 'T<whatever>' type in another static constructor and
the 'dummy' static member may not necessarily be constructed at that time.
See "static object initialisation fiasco" for more information.
An acceptable solution would be
class T
{
struct static_constructor { static_constructor(); };
struct dummy_member { dummy_member(); } dummy;
...
};
T::static_constructor::static_constructor()
{
// do what you need here
};
T::dummy_member::dummy_member()
{
static static_constructor; // this will be initialised only once
}
That way, during the construction of an instance of T, its member 'dummy'
(which will have size 0, since it's a subobject) is constructed and inside
dummy's constructor, a static 'static_constructor' object is constructed
_only once_, at the very first execution of the dummy's c-tor body.
Victor
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Thu Dec 16, 2004 2:01 pm Post subject: Re: Emulating a static constructor |
|
|
[email]glenlow (AT) pixelglow (DOT) com[/email] wrote:
| Quote: | There's a feature I quite like in Java and C# called a "static
constructor". It's just code tied to an object that you want
to execute before the first instance of the object is
created. This can be useful to do complicated initialization
of static data members, and sometimes you don't want to do
this when the first instance is created -- e.g. to avoid
synchronizing such code in the face of multiple threads and/or
you're writing a library and don't want the client to have to
explicitly initialize the package.
Do you think this is a suitable emulation?
class T
{
static int static_constructor () { ...; return 0; }
static int dummy;
}
int T::dummy = static_constructor ();
OR, in the template case:
template <typename U> class T
{
static int static_constructor () { ...; return 0; }
static int dummy;
}
template <typename U> int T <U>::dummy = static_constructor ();
If I read the Standard correctly, the dummy is dynamically
initialized at namespace scope. While it is unspecified
whether it runs before the first statement of main (3.6.2/3),
it must be done before the first use of any function from that
translation unit, which presumably includes constructing
objects of type T. A multithreading-aware compiler should
ensure that this happens before any threads create the
objects.
|
It's a variant of the classical solution. (In a discussion in
the German speaking newsgroup, I think creating a nested type,
and using a static instance of this, was prefered. But it comes
out to the same.)
Note that this DOESN'T guarantee static initialization before
first use of the object. The dynamic initialization is
guaranteed to take place *either* before main *or* before first
use. That's an or, not an and. And in practice, it is always
before main, since the other is extremely difficult, if not
impossible, to ensure.
If there is any possibility of static instances of T, then you
probably want to ensure that static_constructor can be called
multiple times, and call it at the start of each constructor as
well.
--
James Kanze GABI Software http://www.gabi-soft.fr
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Branimir Maksimovic Guest
|
Posted: Thu Dec 16, 2004 6:17 pm Post subject: Re: Emulating a static constructor |
|
|
[email]glenlow (AT) pixelglow (DOT) com[/email] wrote:
| Quote: | There's a feature I quite like in Java and C# called a "static
constructor". It's just code tied to an object that you want to
execute
before the first instance of the object is created. This can be
useful
to do complicated initialization of static data members, and
sometimes
you don't want to do this when the first instance is created -- e.g.
to
avoid synchronizing such code in the face of multiple threads and/or
you're writing a library and don't want the client to have to
explicitly initialize the package.
Do you think this is a suitable emulation?
......
template <typename U> class T
{
static int static_constructor () { ...; return 0; }
static int dummy;
}
template <typename U> int T <U>::dummy = static_constructor ();
Yes, agree, this idiom is very usefull. |
I use this idiom mainly to verify that static initialization
is performed correctly because in some cases wrong linker can
"skip" initialization of statics.
......
| Quote: | A multithreading-aware compiler should
ensure that this happens before any threads create the objects.
|
Forget about threads, if multiple threads start to create
such objects initialization function can be called multiple
times. Compiler must assure that initialization is performed
only once, and that of course means that you must ensure
such behavior(if you wan't to be portable). Or you can predict
that initialization function will be called more then once
at the same time and customize code according to that.
int static_constructor()
{
static bool is_initialised_ = 0;
Lock lock;
if(is_initialised_)return 0;
//... be aware of problems related when thread cancelation
// or forking is done during initialization
// .. or just use pthread_once which assures proper behavior?
is_initialised_ = true;
return 0;
}
Greetings, Bane.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave O'Hearn Guest
|
Posted: Thu Dec 16, 2004 6:21 pm Post subject: Re: Emulating a static constructor |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
| Quote: | Note that this DOESN'T guarantee static initialization before
first use of the object. The dynamic initialization is
guaranteed to take place *either* before main *or* before first
use. That's an or, not an and. And in practice, it is always
before main, since the other is extremely difficult, if not
impossible, to ensure.
|
I'm wondering if it's not only difficult to ensure, but somewhat
futile. What would the mandated behavior be if I had an inline, like
this,
inline void f() { return; }
in a header included in every translation unit? Does my first call to
f() have to initialize the statics in every translation unit?
3.6.2/3 says, "If the initialization is deferred to some point in time
after the first statement of main, it shall occur before the first use
of any function or object defined in the same translation unit as the
object to be initialized."
I generally assume all my statics initialize before main, figuring that
any furture platform where that wasn't the case would be so alien that
I'm going to have issues with it regardless. Still, it would be amusing
to put f(); as the first line in main, and thereby have it be defined
behavior...
--
Dave O'Hearn
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave O'Hearn Guest
|
Posted: Fri Dec 17, 2004 4:44 am Post subject: Re: Emulating a static constructor |
|
|
Dave O'Hearn wrote:
| Quote: | 3.6.2/3 says, "If the initialization is deferred to some point
in time after the first statement of main, it shall occur before
the first use of any function or object defined in the same
translation unit as the object to be initialized."
|
I missed this in 3.2/3, "An inline function shall be defined in every
translation unit in which it is used."
The silliest way I can think to "use" an inline function is this,
// header magic.h
inline void magic() { }
namespace {
int magic_init = (magic, 0);
}
I'm not sure this actually works to require all static init to be done
before main, but it would be amusing if it did, since the construct
doesn't do anything.
--
Dave O'Hearn
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
glenlow@pixelglow.com Guest
|
Posted: Fri Dec 17, 2004 11:14 am Post subject: Re: Emulating a static constructor |
|
|
Surely the compiler must itself ensure that initialization is performed
once only for the program statics? This is probably a QOI issue but it
seems to me that a compiler can either
1. Initialize before main, in which case since (hopefully) only main
spawns threads, the initialization happens exactly once and before any
new threads start running.
2. Initialize during main but before any call of that translation unit.
In which case, if (a big if, of course) the compiler is thread-aware it
must either ensure the initialization occurs before any known
thread-spawing operations or interpose its own synchronization to
prevent multiple initializations.
Cheers, G.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Fri Dec 17, 2004 3:06 pm Post subject: Re: Emulating a static constructor |
|
|
[email]glenlow (AT) pixelglow (DOT) com[/email] wrote:
| Quote: | Surely the compiler must itself ensure that initialization is
performed once only for the program statics?
|
According to what standard? The C++ standard treats all
multithreading as undefined behavior. The Posix standard treats
all C++ as undefined behavior. If you are multithreading in C++
on a Posix platform, all you've got is undefined behavior. And
the compiler implementor's willingness to define certain
undefined behaviors. However he feels like defining them.
| Quote: | This is probably a QOI issue but it seems to me that a
compiler can either
|
Ah, QoI. That, of course, influences (or should influence) how
the compiler implementor defines the undefined behaviors. On
the Posix side, the standard even makes some non-normative
suggestions, e.g. that a pthread_cancel call the destructors of
all of the on stack objects in the thread.
| Quote: | From a QoI point of view, I would consider the following points
evident: |
- That all of the guarantees Posix gives for C hold in the C
compatible parts of C++.
- That the guarentees that Posix gives for basic C objects
also hold for all of the "object" types defined in the C++
standard (e.g. string, vector...).
- That any hints and/or intentions in either of the standards
be respected. (E.g. that pthread_cancel actually call the
destructors for all objects on the stack of the cancelled
thread, in the appropriate order.)
Beyond that, I would also expect things like you suggest,
e.g. that initializers for static objects (including local
static objects) only be called once, that I can call operator
new from more than one thread without synchronizing, etc.
In practice, it ain't that good. At least one major compiler
(g++) doesn't even respect that points that I list as evident,
and none of the compilers I have access to protect the
constructors of locale static objects -- in fact, none even
document what they do.
| Quote: | 1. Initialize before main, in which case since (hopefully)
only main spawns threads, the initialization happens
exactly once and before any new threads start running.
|
All of the compilers I've ever seen do initialize static objects
at namespace scope before main. And all run the static
initializers in a single thread. I have a lot of code that
count on this; given the number of others who also have such
code, I don't really expect it to see anything else.
Provided, of course, that the objects in question have been
statically linked:-).
| Quote: | 2. Initialize during main but before any call of that
translation unit. In which case, if (a big if, of course)
the compiler is thread-aware it must either ensure the
initialization occurs before any known thread-spawing
operations or interpose its own synchronization to prevent
multiple initializations.
|
In practice, initialization of namespace scope statics in a
dynamically loaded object will occur after main, and after
threading has started, and there is nothing that the compiler
can do about it. As far as I can tell (but I've not
investigated this case in complete detail), the load and the
initialization of all of the objects will occur in a single
thread. On the other hand, within the dynamically loaded
object, the ordering is exactly that which would have been had
the object been linked statically. If one of the static
constructor enrolls the object with a registry in the main
module, thus rendering it visible to other threads before all of
the other static objects have been initialized, it will be
possible to call functions in a given module before the static
initialization of the module takes place. Regardless of what
the standard says.
Of course, that's independant of the threading problem. And
equally of course, we still have the problem of local static
objects.
--
James Kanze GABI Software http://www.gabi-soft.fr
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
glenlow@pixelglow.com Guest
|
Posted: Fri Dec 17, 2004 3:07 pm Post subject: Re: Emulating a static constructor |
|
|
| Quote: | template <typename U> class T
{
static int static_constructor () { ...; return 0; }
static int dummy;
}
How? And, yes, in a multi-translation-unit program, I can simply
create
an object of 'T' or 'T<whatever>' type in another static constructor
and
the 'dummy' static member may not necessarily be constructed at that
time.
See "static object initialisation fiasco" for more information.
|
Yes I see that how this defeats the class T solution, but not the
template T solution. The template needs to be instantiated in different
translation units, and has static linkage (IIRC) so it can't be
referenced outside of the translation unit. Therefore each version
within a translation unit must have dummy initialized before first use
of T.
| Quote: | An acceptable solution would be
class T
{
struct static_constructor { static_constructor(); };
struct dummy_member { dummy_member(); } dummy;
...
};
T::static_constructor::static_constructor()
{
// do what you need here
};
T::dummy_member::dummy_member()
{
static static_constructor; // this will be initialised only
once
}
That way, during the construction of an instance of T, its member
'dummy'
(which will have size 0, since it's a subobject) is constructed and
inside
dummy's constructor, a static 'static_constructor' object is
constructed
_only once_, at the very first execution of the dummy's c-tor body.
|
However if two threads simultaneously create an instance of T,
static_constructor might be called twice.
Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Branimir Maksimovic Guest
|
Posted: Fri Dec 17, 2004 4:10 pm Post subject: Re: Emulating a static constructor |
|
|
[email]glenlow (AT) pixelglow (DOT) com[/email] wrote:
| Quote: | Surely the compiler must itself ensure that initialization is
performed
once only for the program statics?
|
No. Fact that threads are not usually started before
initialization is completed, does not necesites
fact that initialization function is not protected
by lock. On some systems/compilers (eg suns cc) you
have to call initialization/deinitialization function
for statics manually after call to dlopen and
before dlclose.
This is probably a QOI issue but it
| Quote: | seems to me that a compiler can either
1. Initialize before main, in which case since (hopefully) only main
spawns threads, the initialization happens exactly once and before
any
new threads start running.
|
That would be perfect, but we have dlopen, fortunatelly
dlopen isn't guaranteed to be thread safe, so it must
be protected by lock in code.
| Quote: |
2. Initialize during main but before any call of that translation
unit.
In which case, if (a big if, of course) the compiler is thread-aware
it
must either ensure the initialization occurs before any known
thread-spawing operations or interpose its own synchronization to
prevent multiple initializations.
|
This case is almost impossible as static initialization
is simply this
load();
init(); // if someone starts thread in this function
// and try to access static data before function completes
// ... guess what happens :)
main(argc,argv);
fini();
same thing is done when calling dlopen, but dlopen must be protected
by lock, so it seems that init functions are not
guaranteed to be thread safe.
Greetings, Bane.
P.S. My conclusion is that I wouldn't worry much as your idiom is safe
in comparision to eg :
static Singleton& instance(){ static Singleton inst; return inst; }
as local statics are not initialized in library initialization
function(s).
Opposite to that, library user *must* assure thread safety of
initialization routines for libraries, and in addition to that,
starting of threads that access static data during library
initialization is not very wise move, so I doubt someone will
excercise that practice:)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Fri Dec 17, 2004 5:34 pm Post subject: Re: Emulating a static constructor |
|
|
[email]glenlow (AT) pixelglow (DOT) com[/email] wrote:
| Quote: | template <typename U> class T
{
static int static_constructor () { ...; return 0; }
static int dummy;
}
How? And, yes, in a multi-translation-unit program, I can simply
create
an object of 'T' or 'T<whatever>' type in another static constructor
and
the 'dummy' static member may not necessarily be constructed at that
time.
See "static object initialisation fiasco" for more information.
Yes I see that how this defeats the class T solution, but not the
template T solution. The template needs to be instantiated in different
translation units, and has static linkage (IIRC)
|
What's "static linkage"? Do you mean "internal linkage"?
| Quote: | so it can't be
referenced outside of the translation unit. Therefore each version
within a translation unit must have dummy initialized before first use
of T.
|
Proof?
| Quote: |
An acceptable solution would be
class T
{
struct static_constructor { static_constructor(); };
struct dummy_member { dummy_member(); } dummy;
...
};
T::static_constructor::static_constructor()
{
// do what you need here
};
T::dummy_member::dummy_member()
{
static static_constructor; // this will be initialised only
once
}
That way, during the construction of an instance of T, its member
'dummy'
(which will have size 0, since it's a subobject) is constructed and
inside
dummy's constructor, a static 'static_constructor' object is
constructed
_only once_, at the very first execution of the dummy's c-tor body.
However if two threads simultaneously create an instance of T,
static_constructor might be called twice.
|
Really? I can't find any word about "threads" in the Standard.
V
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
glenlow@pixelglow.com Guest
|
Posted: Sat Dec 18, 2004 12:22 pm Post subject: Re: Emulating a static constructor |
|
|
| Quote: | From a QoI point of view, I would consider the following points
evident:
- That all of the guarantees Posix gives for C hold in the C
compatible parts of C++.
- That the guarentees that Posix gives for basic C objects
also hold for all of the "object" types defined in the C++
standard (e.g. string, vector...).
- That any hints and/or intentions in either of the standards
be respected. (E.g. that pthread_cancel actually call the
destructors for all objects on the stack of the cancelled
thread, in the appropriate order.)
Beyond that, I would also expect things like you suggest,
e.g. that initializers for static objects (including local
static objects) only be called once, that I can call operator
new from more than one thread without synchronizing, etc.
In practice, it ain't that good. At least one major compiler
(g++) doesn't even respect that points that I list as evident,
and none of the compilers I have access to protect the
constructors of locale static objects -- in fact, none even
document what they do.
|
It would be good for there to be some sort of conformance document, or
even a study done on each compiler's action in the face of
multithreading.
| Quote: | 1. Initialize before main, in which case since (hopefully)
only main spawns threads, the initialization happens
exactly once and before any new threads start running.
All of the compilers I've ever seen do initialize static objects
at namespace scope before main. And all run the static
initializers in a single thread. I have a lot of code that
count on this; given the number of others who also have such
code, I don't really expect it to see anything else.
Provided, of course, that the objects in question have been
statically linked:-).
2. Initialize during main but before any call of that
translation unit. In which case, if (a big if, of course)
the compiler is thread-aware it must either ensure the
initialization occurs before any known thread-spawing
operations or interpose its own synchronization to prevent
multiple initializations.
In practice, initialization of namespace scope statics in a
dynamically loaded object will occur after main, and after
threading has started, and there is nothing that the compiler
can do about it.
|
Your two statements seemed contradictory until I realized you were
talking about DLL-loaded objects in that last paragraph. I think I'm
still safe if the object in question is a template (instantiation),
since it would be in the .h and therefore actually instantiated with
static linkage in the calling code, which then has to ensure that the
"static constructor" is called before any other functions of the
object.
Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Tue Dec 21, 2004 1:00 am Post subject: Re: Emulating a static constructor |
|
|
Branimir Maksimovic wrote:
| Quote: | glenlow (AT) pixelglow (DOT) com wrote:
Surely the compiler must itself ensure that initialization is
performed once only for the program statics?
No. Fact that threads are not usually started before
initialization is completed, does not necesites
fact that initialization function is not protected
by lock.
|
What makes you so sure? I don't particularly like the idea either, but
I've seen code which started threads from the initializers of static
variables.
Let's just say that we choose to retain this as a documented
restriction
in the use of our library:-). That any threads using anything in our
library may not be started until after main has been entered.
| Quote: | On some systems/compilers (eg suns cc) you
have to call initialization/deinitialization function
for statics manually after call to dlopen and
before dlclose.
|
Are you sure? I get my static constructors called by dlopen, and I
don't do anything special that I know about.
| Quote: | This is probably a QOI issue but it seems to me that a compiler can
either
1. Initialize before main, in which case since (hopefully) only
main
spawns threads, the initialization happens exactly once and
before any new threads start running.
That would be perfect, but we have dlopen, fortunatelly
dlopen isn't guaranteed to be thread safe, so it must
be protected by lock in code.
|
Not according the the X Open System specification. On the other hand,
there is very little said about the interactions between these
functions
and threading. dlopen and dlclose (but not dlsym) may be cancellation
points. Or not, depending on the implementation. Presumably (because
nothing else is said) the entire function (including the execution of
static initializers) runs in the calling thread. On the other hand,
there doesn't seem to be any specification concerning memory
synchronization; theoretically, at least, that means that you may not
see the results of the static initializers. In practice, I don't think
that this is a problem: In order for any other thread to see the
results
of these functions, the calling thread will have to communicate them to
the other thread. This means some sort of synchronization between the
two threads, and all of the synchronization requests imply memory
synchronization as well.
| Quote: | 2. Initialize during main but before any call of that translation
unit. In which case, if (a big if, of course) the compiler is
thread-aware it must either ensure the initialization occurs
before any known thread-spawing operations or interpose its own
synchronization to prevent multiple initializations.
This case is almost impossible as static initialization
is simply this
load();
init(); // if someone starts thread in this function
// and try to access static data before function completes
// ... guess what happens :)
main(argc,argv);
fini();
same thing is done when calling dlopen, but dlopen must be protected
by lock, so it seems that init functions are not guaranteed to be
thread safe.
|
According to the X Open System specifications, the dlopen, dlsym and
dlclose functions themselves must be thread safe, i.e. I can call them
in parallel on different objects in different threads. Presumably, the
various initializations of static objects will occur in the calling
thread, or at least, it will appear so. (The system could use a
special
thread of its own for this, but it must synchronize this thread.)
Exactly what this means depends on the implemenation; X Open System
says
nothing about the initializers of static objects. But it seems
reasonable to include this initialization as part of the dlopen call,
and in fact, this is what both Sun and Linux apparently do.
| Quote: | P.S. My conclusion is that I wouldn't worry much as your idiom is
safe
in comparision to eg : static Singleton& instance(){ static Singleton
inst; return inst; } as local statics are not initialized in library
initialization function(s).
|
Quite. It is, in fact, very important that the initialization have
been
fully finished before any other thread can possibly see the results,
AND
that there be something that synchronizes the memory between the end of
the initialization and the uses the object in another thread. If we
require that any thread using the Singleton be started after main,
pthread_create or the requests which synchronize the accesses to the
data returned from dlopen and dlsym ensure the synchronization,
provided
that the initialization is called at least once during static
initialization.
--
James Kanze GABI Software http://www.gabi-soft.fr
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|