TITLE: thread safe singleton (Newsgroups: comp.lang.c++.moderated, 1 Mar 2000) DYCK: Ken Dyck |> > But, how about the following: |> > |> > class Singleton { |> > public: |> > |> > static Singleton& instance () { return theSingleton; } |> > |> > private: |> > |> > Singleton () {} |> > |> > static Singleton theSingleton; |> > } |> > |> > Singleton Singleton::theSingleton; |> > |> This might not be safe if Singleton::instance() is called from |> another static object. That is, Singleton::theSingleton may be used |> before it's initialized. |> > |> To avoid this problem, I'd suggest: |> > |> class Singleton { |> public: |> > |> static Singleton& instance (); |> > |> private: |> > |> Singleton () {} |> }; |> > |> > |> Singleton& Singleton::instance() |> { |> static Singleton theSingleton; |> return theSingleton; |> } |> > |> This way theSingleton will be initialized on first use. KANZE: kanze@gabi-soft.de The original question was for a thread-safe version. This isn't. Technically speaking, you can't write anything thread safe in C++, since the language doesn't provide any support for threading. In practice, in order to write a thread safe version, you have to know exactly what the compiler guarantees with regards to threading. The simplest version would be: Singleton& Singleton::instance() { <> static Singleton* result ; if ( result == NULL ) { result = new Singleton ; } <> return *result ; } This version is pretty safe, IMHO -- it's hard to imagine a thread-aware compiler shifting the memory accesses accross the locking and unlocking code. On the other hand, it can be extremely expensive, since you grab the lock *every* time you want an instance. One frequently proposed alternative is: Singleton& Singleton::instance() { static Singleton* result ; if ( result == NULL ) { <> if ( result == NULL ) { result = new Singleton ; } <> } return result ; } Whether this works or not depends on your compiler -- there are at least two ways it can fail: - The compiler, noting that nothing can change the value of result between the two tests, saves it in a register. This can be easily avoided by declaring the variable volatile. Or a thread-aware compiler will know enough to "forget" the contents of registers whenever it sees a lock. - The compiler may rearrange the order of the writes, so that the write to result precedes some of the writes in the constructor of Singleton. In practice, very few compilers are this good at optimizing *if* the constructor to Singleton is not inline. Now, anyway -- watch out for the next version. Regrettably, I know of no easy way around this, except to use a second lock around the constructor, but with the assign to result outside of the locked area, simply to signal to a thread-aware compiler that it must flush registers. _______________________________________________ cpptips mailing list http://cpptips.hyperformix.com