"However, I would strongly recommend against relying on this, as the smallest change could affect the behaviour so that it is no longer what you may expect."
You're preaching to the choir. :-)
"In particular, the compiler may choose to generate the write to pInstance before it invokes the constructor of the new Singleton object"
Even with optimisation turned off? Remember, I'm trying to crack through "if it's not broken, don't fix it", so I'll have to be convincing.
"If you are going to rely on compiler and platform specific behaviour, then you are better off using the compiler-specific atomic primitives such as the gcc __sync_xxx builtins. Such primitives will have a documented consequence on the compiler behaviour, and might therefore provide the requisite guarantees."
Seems like overkill: they're documented as "full barrier", which is too expensive (I only need release-store and load-acquire,which shouldn't take more thana single MOV of properly aligned data).
if(!objectPointer) objectPointer = new Object; // has non-trivial ctor
Thread A could potentially issue objectPointer->DoWork(); prior to completion of construction
if(!objectPointer) objectPointer = getNewObject();
return new Object;
Above is safe provided only one instance of thread B code runs
If/when multiple threads perform above, you could have multiple new's overwriting one pointer.
Object* temp = new Object;
if(CAS(objectPointer, 0, temp))
Above is safe even if multiple attempts to allocate begin.
Note, the errant allocation could be preserved by placing into an additional location for use later.
(assuming that pointer is NULL).
So you're giving me just enough information to stress me out, and not enough to force a change... :-/
I guess if we'll just keep our fingers crossed, and occasionally light a candle, that ought to do the trick.