Re: Singleton Pattern
On Apr 19, 6:07 am, Keshav <gupta.kes...@gmail.com> wrote:
HI,
I would like to know whetehr this is the right way to implement
thread safe singleton.
Generally we do locking and all at Instance method, Can we get rid of
these problems if we create instance while defining pInstance
variable.
Would it create any problem?
[snip]
There are 3 issues when creating a singleton in C++ that you have to
worry about:
- static initialization order fiasco (see the C++ FAQ)
- static de-initialization order fiasco (see the C++ FAQ)
- thread-safety (see any standard piece on thread safety in C++. I
strongly suggest
http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
as one of the best papers on the topic.)
If you can guarantee that no other global (or namespace) object will
use your singleton, then you can ignore static initialization order
problems and static de-initialization order problems. (This is not
something you can usually safely assumption. This is bad style to
assume this as it is fragile. Someone somewhere else can break your
code with touching your code at all. I will thus ignore this
possibility here.)
Your options are "eager-initialized initialized-on-demand singleton"
or "lazy-initialized initialized-on-demand singleton". There are
several implementations for each, depending on the threading primitive
you want to use.
An example implementation of "eager-initialized initialized-on-demand
singleton" (left as an exercise to determine which parts go in the
header and cpp). (Note that access to the singleton itself may require
a mutex. This just guarantees a single thread-safe construction.)
class singleton_t {};
singleton_t & getSingleton()
{ static singleton_t * x = 0;
if ( ! x)
x = new singleton_t;
return *x;
}
/* Eager initialize the singleton to ensure it's created before main,
and thus before there are multiple threads. If threads are created
before main, then it's impossible to do this safely in C++03.*/
namespace
{ struct EagerInitialize { EagerInitialize() { getSingleton(); } };
EagerInitialize instEagerInit;
}
An example implementation of "lazy-initialized initialized-on-demand
singleton" (left as an exercise to determine which parts go in the
header and cpp). (Note that it contains eager-initialization
initialization-on-demand of the guarding mutex.) (Note that access to
the singleton itself may require a mutex. This just guarantees a
single thread-safe construction.)
//from threading library
class mutex {};
class guard { public: guard(mutex& ); ~guard(); };
mutex & getSingletonMutex()
{ static mutex * x = 0;
if ( ! x)
x = new mutex;
return *x;
}
/* Eager initialize mutex to ensure it's created before main, and thus
before there are multiple threads. If threads are created before main,
then it's impossible to do this safely in C++03.*/
namespace
{ struct EagerInitialize { EagerInitialize() { getSingletonMutex
(); } };
EagerInitialize instEagerInit;
}
class singleton_t {};
singleton_t & getSingleton()
{ guard g(getSingletonMutex());
static singleton_t * x = 0;
if ( ! x)
x = new singleton_t;
return *x;
}
Other implementations are possible with memory barriers or other
threading primitives, but those are the simple ones using the simplest
and most portable threading primitive, mutexes.