Subj : Re: Boost.Threads on its way to C++0x To : comp.programming.threads From : gottlobfrege Date : Wed Apr 27 2005 04:07 pm Peter Dimov wrote: > 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.) Nothing wrong with it really. But if you want, you can delay/avoid creating the named mutex until thread contention occurs. Which would make the typical path faster. .