On Dec 7, 2012, at 2:04 PM, Ken Thomases <k...@codeweavers.com> wrote:
> On Dec 7, 2012, at 3:08 PM, Greg Parker wrote:
>> 
>> You can't assume that any instance variables of a newly initialized object 
>> have been zeroed out when
>> * you are reading them from threads other than the one that allocated the 
>> object and 
>> * there is no synchronization between the allocating thread and the reading 
>> thread.
>> 
>> In ordinary code there is only one thread involved, or there is already some 
>> thread synchronization somewhere. 
>> 
>> For example, the allocating thread acquires a lock before writing the new 
>> object's pointer somewhere that the reading thread can see it, and the 
>> reading thread takes the same lock before reading the object pointer. That 
>> lock is sufficient synchronization to make it work.
>> 
>> You'll only run into trouble if you are trying to use lock-free 
>> multiprocessing techniques and you don't use enough memory barriers.
> 
> But this means that dispatch_once() is not uniquely unsafe.  It can fail only 
> in the exact same scenarios where a thread other than the one which allocated 
> an object might see uninitialized values for generic instance variables.  
> Such scenarios are, of course, unacceptable and so proper synchronization is 
> necessary when passing object pointers between threads, full stop.  There's 
> no special care necessary to make dispatch_once() safe, there's just the 
> ordinary care necessary to make passing of object pointers between threads 
> "sane".

That's right. The problem specific to dispatch_once() is that people sometimes 
use dispatch_once() in lieu of other synchronization expecting dispatch_once() 
itself to provide more synchronization than it actually does. 


> You said that dispatch_once() doesn't promise to provide memory barriers, 
> but, since the use of GCD hasn't brought catastrophe down on all of our 
> heads, I assume that dispatch_async() and the like do provide such memory 
> barriers.  Likewise, NSOperationQueue, -performSelector:onThread:..., and the 
> like must also.  Is that right?

I would expect that any multiprocessing primitive that does not provide 
sufficient memory barriers for some uses would document that fact loudly. 
dispatch_once()'s storage is one documented example of missing barriers. Some 
of the OSAtomic functions are another example. But pretty much everything 
heavier-weight than that ought to provide complete memory barriers for any 
clients.


> If you wanted to be paranoid about using an instance variable as a once 
> predicate, is it sufficient to use OSMemoryBarrier() in the -init method of 
> the object?  Or perhaps there needs to be another call to OSMemoryBarrier() 
> immediate before the dispatch_once() call, too.

Maybe. It depends on the architecture and the precise implementation of 
dispatch_once(). 

My guess is that OSMemoryBarrier() in -init is sufficient for 
dispatch_once(&ivar) on all current OS X and iOS architectures and any other 
reasonable architectures, and is required on some of them.

(As usual, the "unreasonable" architecture is the DEC Alpha, whose memory 
consistency rules were too loose for mere humans to manage correctly. It looks 
like everyone learned since then that putting zero data-dependency enforcement 
in the CPU was a step too far.)


-- 
Greg Parker     gpar...@apple.com     Runtime Wrangler



_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to