Sorry for my poor English , I am not the native English speaker.
I start using Mangos for only one day , and I also try to read some of the source files. I do not know my source code version is the newest,
my version is mangos-0.9.0 , if this bug has been fixed in the later version , just skip this topic .
I just read the file SingletonImp.h , and I found the coder using the double-lock routine for implementing the lazy instance.
However , this mechanism does not work on the SMAP cpu , which means on many multi-core , there exist potential hazard
while on the initialization .
The reason can be obtained by google the key word : Memory Barrier .
Here I just give the revision version , which I does not prove it is right , just tips.
// a memory barrier wraper
// this memory barrier indeed will lock the bus and notify all the core to flush their own cache
// in order to get the same and accurate value
// calling this function will make all the store-and-load operation before such calling strictly be finished.
static void MemoryBarrier() {
#if defined (__MSV_VER)
::MemoryBarrier();
#elif defined (__GNUG__)
__volatile __asm (""::: " memory " );
#endif
}
template
<
typename T,
class ThreadingModel,
class CreatePolicy,
class LifeTimePolicy
>
T&
MaNGOS::Singleton<T, ThreadingModel, CreatePolicy, LifeTimePolicy >::Instance()
{
//add
T& value = si_instance;
MemoryBarrier();
// here the value has been notified
if( !value )
{
// double-checked Locking pattern
Guard();
// since reach here , there exist no other thread gonna get in
// so it is safe to use the si_instance itself
if( !si_instance )
{
if( si_destroyed )
{
LifeTimePolicy::OnDeadReference();
si_destroyed = false;
}
si_instance = CreatePolicy::Create();
// we should make sure the value (address) has indeed been written into that pointer (si_instance)
// so flush this value
MemoryBarrier();
LifeTimePolicy::ScheduleCall(&DestroySingleton);
}
}
return *si_instance;
}
Since I havn't read the code about the time schedual of every singleton instance , maybe using the atexit function ,
so the si_destroy variable I do not revise it. Anyway , if there do need the revision , it is pretty easy .
Another thing is : using the key word "volatile" before the variable si_instance and si_destroy , since those two variables can
be accessed by two different threads or more , therefore it is safe to do this (however, this does not mean it is absolutely safe ) and this will
force compiler to generate better thread safe machine code.