Re: Singleton_pattern and Thread Safety
On 13/12/2010 11:09, James Kanze wrote:
On Dec 11, 7:57 pm, "Chris M. Thomasson"<cris...@charter.net> wrote:
"Leigh Johnston"<le...@i42.co.uk> wrote in message
news:aI-dnTRysdoEVJ7QnZ2dnUVZ7sSdnZ2d@giganews.com...
On 11/12/2010 18:47, Chris M. Thomasson wrote:
[...]
Thanks for the info. At the moment I am only concerned with
IA-32/VC++ implementation which should be safe.
FWIW, an atomic store on IA-32 has implied release memory
barrier semantics.
Could you cite a statement from Intel in support of that?
Also, an atomic load has implied acquire semantics. All
LOCK'ed atomic RMW operations basically have implied full
memory barrier semantics:
http://www.intel.com/Assets/PDF/manual/253668.pdf
(read chapter 8)
In particular, ?8.2.3.4, which specifically states that "Loads
may be reordered with earliers storead to different locations".
Which seems to say just the opposite of what you are claiming.
Also, latest VC++ provides acquire/release for volatile load/store
respectively:
http://msdn.microsoft.com/en-us/library/12a04hfd(v=VS.100).aspx
(read all)
So, even if you port over to VC++ for X-BOX (e.g., PowerPC), you will get
correct behavior as well.
Provided he uses volatile on the pointer (and uses the classical
double checked locking pattern, rather than his modified
version).
To which version are you referring? The newest version does not use
volatile nor needs volatile. There is a barrier after the first fast
check and whilst this barrier is a no-op on my implementation it does
prevent compiler reordering. My version is not the same as the
traditional double checked locking pattern if you care to look (there is
only one "pointer check". My version is the Meyers Singleton which is
superior to your hogwash leaky version.
Again:
template <typename T>
class singleton
{
public:
static T& instance()
{
T* ret = static_cast<T*>(sInstancePtr);
lib::memory_barrier_acquire_dependant();
if (ret == 0)
{
lib::lock lock1(sLock);
static T sInstance;
lib::memory_barrier_release();
sInstancePtr = &sInstance;
ret = static_cast<T*>(sInstancePtr);
}
return *ret;
}
private:
static lib::lockable sLock;
static singleton* sInstancePtr;
};
template <typename T>
lib::lockable singleton<T>::sLock;
template <typename T>
singleton<T>* singleton<T>::sInstancePtr;
/Leigh
/Leigh