
On Thu, Jun 30, 2011 at 4:40 PM, Gruenke, Matt <mgruenke@tycoint.com> wrote:
On June 28, 2011 03:29, Ben Robinson wrote:
T *Get_single() __attribute__ ((const,nothrow)) { T *s = Single_inst.get(); if (!s) { if (Single_inst.try_init_lock()) { s = Single_inst.init_locked(new T()); } else s = Single_inst.get_blocking(); } return s; }
I think you need a memory barrier after setting s, as well as on the if (!s) test. The assignment to s can drift upwards and *into* the init_locked() or get_blocking() calls, including drifting up above an unlock() inside those functions. Then another thread, at if (!s) will see s as set, but maybe not all the members of T will have been initialized yet. Yet s is returned and used... Or do you have a full read-write barrier at the end of init_locked() and get_blocking(). Also what barrier, if any, is inside get()? I'd suggest using boost::call_once(). Tony