Subj : Re: Boost.Threads on its way to C++0x To : comp.programming.threads From : Peter Dimov Date : Wed Apr 27 2005 03:21 pm gottlobfrege@gmail.com wrote: > Another way of looking at it is consider the case of making a > 'StaticLocalCriticalSection' C++ object. Say this object wraps a > Windows CRITICAL_SECTION (which needs an init) in a only-init-once > way. How? > > class StaticLocalCriticalSection > { > atomic_int started; > atomic_int initted; > CRITICAL_SECTION cs; > > // this class must NOT have a constructor > // (at least not one that does anything) > // Instead we assume that we are static, > // and thus 'started' and 'initted' are both set > // to 0, effectively at compile time. > > void ensure_initted() > { > if (!AtomicExchange(&started, true)) > { > InitCriticalSection(&cs); > AtomicExchange(&initted, true); > } > else > { > // There's better ways to do this than spinning, > // but this is make the example shorter. > // In fact, this example has a starvation problem, > // if this thread has a higher priority > // than the init thread. > // (ie may never get a chance to be initted) > > while (!AtomicRead(&initted)) > { > Sleep(1); > } > } > } Sleep(1) yields to lower priority threads, BTW. [...] > And you will find the same/similar logic in call_once/pthread_once. > That's why I say they are all 'equivalent' and given any one you can > write the others. Almost... an enhanced call_once that takes a function object (or a pthread_once that takes a void* argument and passes it to the init routine) can be used, but the current forms cannot. struct StaticCriticalSection { CRITICAL_SECTION cs; void ensure_initted() { call_once( boost::bind( InitializeCriticalSection, &cs ) ); } }; (once flag omitted for brevity ;-) ) This is one of the enhancements that I have in mind for Boost.Threads - you mentioned it too in your original post. The current Windows implementation of call_once uses double-checked locking with a named mutex (algorithm by Alexander Terekhov as usual, to the best of my knowledge). Why don't you like it? Is there something wrong with it? (Except that it's implemented poorly, but this can be taken care of.) .