Subj : Re: Can C++ local static objects be made thread safe? To : comp.programming.threads From : Giancarlo Niccolai Date : Wed Feb 02 2005 03:49 pm Gianni Mariani wrote: > Alexander Terekhov wrote: >> Gianni Mariani wrote: >> [...] >> >>>I don't think so. Having heard the growlings of a colleague recently, I >>>suspect there are at least 2 people that violently disagree with you. >>> >>>Do explain what you think is so silly. >> >> >> "You should not pay for what you don't use" motto, you know. For >> mutable static locals, you must synchronize operations (I mean >> apart from init) anyway. So, apart from mutable static locals >> atomic<>"-ized internally, you better simply stick to some lock >> (e.g. POSIX's statically initialized mutex or rwlock) for both >> init and subsequent operations on "threads unaware" static local. >> That's just one example where compiler synchronized static local >> is totally useless. > > Since this synchronization overhead is performed exactly once per static > local and the number of static locals is usually very limited (and by > defintiion cannot exceed the some factor multiple of the size of the > code, the overhead is probably so negligible that the cost of potential > errors by far exceeds the benefits of the "not pay for" motto. > > By the number of people I know of that are bitten by this issue, this is > a significant problem and solving it once and for all is > "The Way To Go"(TM) First of all, we can discuss on what is the "Way To Go"(TM); IMHO, it is NOT having the compiler to do sync for you, because as I say (as we are getting in mottos), "There is no shortcut to threading". You have to do it right, or prevent doing it at once; you cannot expect to have automated mechanism to do it for you, as the JAVA lesson shown; or you can, but only for limited projects, as a "limited" paradigm cannot resolve (by definition) the general case. Secondly, the problem with COFU semantic is that, unless you can demonstrate that all the COFU have already been called, you have ALWAYS to call the static initializer routine, and you can never access the objects directly inside the program. That's put a call overhead EVERY TIME YOU ACCESS AN OBJECT which responds to the COFU semantic (excluding the places where the compiler caches the COFU routine return value). This cost goes beyond the simple call, push bp, mov bp,sp, cmp already_initialized, 0, je already_initialized, mov ax, val, ret cost (more or less, which is anyway quite enough for my taste); it has also an hidden cost in optimization opportuintes missed by the compiler and localty/L1 cache misses at runtime. So, COFU are down in first place, and MUST be avoided when any other technique is possible (again, this is the result of C++ FAQ Lite, based on the comp.language.c++ experience, and it is not a consideration of mine). But adding a mutex lock/unlock with potential useless context swap at each object access (because each object access should enter that call and make the comp already_initialized,0 atomic), even if i.e. you just wanted to read it, or you had to synchronize it afterwards on YOUR rules, it's more than silly: it's mad. Especially if you can do it right without it, and believe me, you can. Giancarlo. .