
Roland Schwarz wrote:
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.
indeed.
In a templated function
template<typename DerivedT, typename ContextT, typename ScannerT> inline typename DerivedT::template definition<ScannerT> & get_definition(grammar<DerivedT, ContextT> const* self) { ... typedef grammar<DerivedT, ContextT> self_t; typedef impl::grammar_helper<self_t, DerivedT, ScannerT> helper_t; typedef typename helper_t::helper_weak_ptr_t ptr_t;
static boost::thread_specific_ptr<ptr_t> tld_helper; if (!tld_helper.get()) tld_helper.reset(new ptr_t); ptr_t &helper = *tld_helper; ... }
a local static thread_specific pointer is beeing used for thread safety. To make this really thread safe the pointer normally should be declared at global (namespace) scope. This is not possible in this case, since the pointer type is parameterized on a template parameter.
What's wrong with simple: template <typename T> struct wrapper { static T data; }; template <typename T> T wrapper<T>::data; template<C> void foo(C arg) { bar<C>& abar = wrapper<bar<C> >::data; } ... which will trigger static (thread-safe) initialization. B.