
Roland Schwarz <roland.schwarz@chello.at> writes:
Initialisation of local static objects is potentially not thread-safe.
From this it follows that the constructor call poses a race condition, when a second thread is making a call to foo, while the first still is in the constructor of bar.
3)-- Use a static pointer to the object and initialize on first use, by making use of boost::call_once. Based on this idea I wrote a little class wrapper that can be used as following:
template<C> void foo(C arg) { static once_class<bar<C> > static_abar = ONCE_CLASS_INIT; bar<C>& abar(static_abar);
... abar.blah(); ...
}
Solution 3) does not suffer from the single point of synchronization drawback and can make any default constructible object statically initialzeable in a thread-safe manner. This of course can also be used to declare a (global) mutex that needs to be available from within global ctor's.
I have attached a commented implementation of this class wrapper together with a sample usage.
I would be glad to get feedback on this design, before adding it to the boost::thread library.
On Windows we don't need two calls to call_once, as my implementation allows passing an arbitrary functor, which can therefore have state (e.g. use bind to pass parameters). Your code demonstrates how we could provide the same facility with pthreads, as an extension to call_once. Incidentally, whilst we're thinking about this, the POSIX spec says: "The behavior of pthread_once() is undefined if once_control has automatic storage duration or is not initialized by PTHREAD_ONCE_INIT." So we need to document this restriction on the use of boost::once_flag, unless you can find a way round it. This restriction doesn't apply on Windows, at least not with my implementation. Anthony -- Anthony Williams Software Developer Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk