Subj : Re: Can C++ local static objects be made thread safe? To : comp.programming.threads From : Gianni Mariani Date : Wed Jan 19 2005 11:04 pm David Hopwood wrote: > David Schwartz wrote: > >> "Marcin 'Qrczak' Kowalczyk" wrote: >> >>>> Lock what exactly? How should the compiler know what the constructor >>>> might conflict with and what locks might be appropriate? >> >> >>> I mean static variables in functions, which are initialized when the >>> function is run for the first time. >> >> >> I'm still baffled. >> >>> Static (and extern) variables outside functions, initialized at the >>> beginning of the program, are another story with different problems. >> >> >> Okay, but what should be locked? Are you suggesting that every >> single construction of a static object should be treated as if it were >> bracketed by a lock/unlock pair of a single global mutex? > > > No, why would that be necessary? It can be implemented by any means > that guarantees that the initialization is done exactly once before the > subsequent function body is executed. Some ways to do that are: > > - bracket each static local initialization by a lock/unlock of a mutex > specific to that initialization, This would lead to possible deadlock with recursive constructors. > - bracket each static local initialization by a lock/unlock of a mutex > shared by some set of initializations, You would need to create some kind of extension for this in the language to identify the grouping. > - move the initialization to an earlier point where it is guaranteed > to be single threaded, Can't allways be done. (loading a DLL for example) > - determine by compile-time or link-time analysis whether the function > might be called by multiple threads, and use one of the above > approaches only if it might. > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13684 The gcc bug-fix does somthing like this the macro below. Basically, once the object is initialized, the cost is virtually the same as it is without the MT-safe code. The overhead is negligible. #define MTSafeStatic( Type, Name, Initializer ) \ static Type * x_ ## Name; \ \ if ( ! x_ ## Name ) \ { \ Lock l_lock( StaticInitializerMutex );\ \ if ( ! x_ ## Name ) \ { \ static Type v_ ## Name Initializer; \ \ x_ ## Name = & v_ ## Name ; \ } \ } \ \ Type & Name = * x_ ## Name; \ // End macro // Note that there must be exactly one StaticInitializerMutex // otherwise you will be making deadlock posssible when // you have recursive constructors .