
Steven Watanabe wrote:
AMDG
Andrey Semashev <andysem <at> mail.ru> writes:
I guess the only way to safely initialize a static local variable is through some call_once concept implementation. The problem in my case is that I'd like the library to be as light as possible and as fast as possible, so I can't make use of Boost.Thread for now.
I believe that volatile works just as well here as it does for m_StatesInfo.
template<class Dispatcher> struct static_event_dispatcher { static volatile bool initialized; //Dispatcher must have a trivial default constructor static Dispatcher dispatcher; static Dispatcher& value() { if(!initialized) { const_cast<volatile Dispatcher&>(dispatcher).init(); initialized = true; } return(dispatcher); } };
template<class Dispatcher> static volatile bool static_event_dispatcher<Dispatcher>::initialized = 0; template<class Dispatcher> static Dispatcher static_event_dispatcher<Dispatcher>::dispatcher;
As Andrei Alexandrescu explains in the following article: http://www.ddj.com/dept/cpp/184403766 a volatile-declared variable of primitive type only hinders the compiler to cache its value in a processor register. It doesn't prevent any race conditions in an MT application. In your code one thread can be in the middle of executing init() when another thread evaluates the condition in the if statement. Clearly, this will lead to two threads calling init(), possibly even at the same time. Even if you rewrite the code as follows // above same as before if(!initialized) { initialized = true; const_cast<volatile Dispatcher&>(dispatcher).init(); } // below same as before there's still a race condition. Two threads could evaluate initialized at the same time... All this even ignores weaker memory models of SMP machines where changes to initialized in one processor are not even visible to threads running on another processor unless you use a memory barrier. -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.