Subj : Re: Can C++ local static objects be made thread safe? To : comp.programming.threads From : Giancarlo Niccolai Date : Thu Feb 03 2005 10:11 pm Gianni Mariani wrote: >> >> So, even if constructors were built right in a MT environment, if they do >> depend on each other in a pure parallel fashion, how may a generic >> program ever hope to work correctly? > > Simply because the C++ standard is quite specific in that static > function local variables (non POD) must be initialized exactly once on > the *first time* that control passes through the variable. All we're > doing here is enforcing this requirement. Perfect. So, what's the problem in having a mutex built before you first need the thing that are willing to use that mutex? Why do a compiler having this for you should make your program better? > > And if there isn't any hope to make the very >> generic program using randomly initialized constructors in a MT >> environment to work correctly, due NOT to language missing features but >> to the impossibility to manage the general parallel flow case, how can >> ever be useful a thing allowing you to reach safely such an unsafe state? > > static local variables is the only mechanism that guarentees order of > construction of singletons. Singletons are a very important concept of > OO programming. No. It isn't. You may also: class Alpha { .... body ... }; static Alpha *ptr_to_alpha; .... main() { ptr_to_alpha = new Alpha; } There is actually no need for a singleton non POD, even for a GLOBAL or module static one, to be initialized during static initialization phase. You can also create it in the main. Or if you don't want to use the new operator to avoid using the heap (which is silly as the objects may and usually will have some internal member allocated there), you can always: class Alpha { .... body ... }; static Alpha & access_alpha() { static *ptr_to_alpha = NULL; if ( ptr_to_alpha = NULL ) ptr_to_alpha = new Alpha; return *ptr_to_alpha; } .... main() { // crete alpha in case static initializers have not done it. access_alpha(); } > >> >> A program with parallelism in its static constructor MAY work, and it MAY >> take advantage from an automated constructor protection mechanism, but >> that would not be the generic case anyhow; it would do only for limited >> interaction between parallel agents that cannot be controlled before the >> program steps in. > > As far as I can tell, the solution that GCC has adopted is a clean and > very general solution to an otherwise very messy problem. > > So, how this technique, applied to the generic case, may >> ever be useful? > > For static local variables to work *at all* in an MT environment, > somthing like what is described earlier in this thread is required, > otherwise your code is broken. Excuse me, but I don't buy it. I have no static initializers in MT code (and if I had, I would have COFUED them, eventually COFUING the mutex in the other variable COFU). In fact, you are still missing the point; I cite you again: > Simply because the C++ standard is quite specific in that static > function local variables (non POD) must be initialized exactly once on > the *first time* that control passes through the variable. All we're > doing here is enforcing this requirement. Yes. The problem here is that I want to be in control of what happens when the object is accessed the *first time*. Also, I did not speak about this topic before, but you must be aware of the fact that locking an unknown piece of code in MT environment, especially when using reentrant mutexes, may lead to cross-locking or other potential causes for deadlocking. If you don't get this point I can descend into details, but just try to immagine what happens if I try to initialize a mutex wrapper from a constructor and then I use this mutex to do some job... another initializer, from another thread, gets the compiler-lock and then tries to acquire my personalized mutex... (that is my first concern, and the reason why, if such a thing is in the compiler, it must be at least possibly turned off. Especially if the initialization is non trivial, you may have blocking functions or crosslocking breaking completely the program, while everything would have been fine without the "help" of the compiler). Gian. .