Re: How to implement readonly property

2012-12-09 Thread Jean-Daniel Dupas

Le 9 déc. 2012 à 02:27, Richard Heard heard...@gmail.com a écrit :

 Greg, 
 
 So, from what you are saying, either of these snippets should be valid, right?
 
 +(id)sharedInstance{
static id _sharedInstance = nil;
 
   …

OSMemoryBarrier();
return _sharedInstance;
 }

OSMemoryBarrier are not cheap. If dispatch_once uses it only on the write side, 
then it should be faster than forcing a full barrier at each access.

By the way, as nobody mention it until then, all this discussion look like to 
me as pointless premature optimization. If accessing your singleton is a 
bottleneck (and nothing tell us it is), there is probably simpler way to avoid 
this cost.

 vs
 
 +(id)sharedInstance{
static id _sharedInstance = nil;
 
static dispatch_once_t onceToken;
dispatch_once(onceToken, ^{
_sharedInstance = [[super allocWithZone:NULL] init];
});
 
return _sharedInstance;
 }
 
 
 Any massive advantages / disadvantages with either approach?
 
 -Richard
 
 On 08/12/2012, at 4:45:37 PM, Greg Parker gpar...@apple.com wrote:
 
 On Dec 8, 2012, at 11:17 AM, Steve Sisak sgs-li...@codewell.com wrote:
 At 10:24 AM -0800 12/8/12, Kyle Sluder wrote:
 On Dec 8, 2012, at 10:06 AM, Steve Sisak sgs-li...@codewell.com wrote:
 
 Further, if writes were not complete at the end of the block, the 
 construct would besentially useless for its intended purpose.
 
 By the way, you're wrong about this too. All @synchronized does is act as 
 a mutex around a code block. It does not cause the compiler to reorder 
 instructions and issue memory barriers in such a way that initialization 
 is guaranteed to precede assignment from the perspective of all threads.
 
 Please cite a source for this assertion.
 
 Source: me, the author of the current @synchronized implementation. 
 @synchronized performs the same synchronization as a pthread mutex.
 
 
 From:
 
 https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html
 
 If you are already using a mutex to protect a section of code, do not 
 automatically assume you need to use the volatile keyword to protect 
 important variables inside that section. A mutex includes a memory barrier 
 to ensure the proper ordering of load and store operations.
 
 To a close approximation, you should pretend that `volatile` does not exist 
 in C-based languages.
 
 The above says that if you already have mutexes then you do not need 
 `volatile`. The mutex alone does all of the work. 
 
 Conversely, `volatile` with no mutex is also not a safe multithreading 
 pattern.
 
 
 I acknowledge that, without proper memory barriers, double-checked locking 
 is problematic, but am providing an example using a construct which I'm 
 fairly sure uses proper memory barriers.
 
 - (NSDictionary *)someDictionary;
 {
 if (!_someDictionary)
 {
 @synchronized (self)
 {
   if (!_someDictionary)
   {
 // create a temp dictionary (might take some time)
  _someDictionary = temp;
   }
 }
 }
 
 return _someDictionary;
 }
 
 
 The example provided does not use proper memory barriers. 
 
 In general, memory barriers need to occur in pairs, one on each thread. The 
 coordination of the two memory barriers achieves the desired 
 synchronization, so that both sides observe events occurring in the same 
 order.
 
 Mutexes and similar constructs achieve this. The mutex lock() and unlock() 
 procedures form a barrier pair. Code running with the mutex held is 
 therefore correctly synchronized with respect to other code that runs with 
 the mutex held. But code running outside the mutex is not protected, because 
 it didn't call the barrier inside the lock() procedure.
 
 In faulty double-checked locking code, the problem is that the writer has a 
 memory barrier but the reader does not. Because it has no barriers, the 
 reader may observe events occur out of the desired order. That's why it 
 fails. (Here the writer is the thread actually calling the initializer and 
 the reader is a second thread simultaneously performing the double-check 
 sequence.)
 
 (Faulty double-checked locking code has a second problem because the 
 writer-side barrier inside the mutex unlock is the wrong barrier to use with 
 a reader that is not locking the mutex.)
 
 You need to do one of two things to fix the reader side of a double-checked 
 lock:
 * add appropriate barriers to the reader side, or 
 * cheat in a way that is guaranteed to work on all architectures you care 
 about.
 
 dispatch_once() actually cheats. It performs a very expensive barrier on the 
 writer side (much more expensive than the barriers used in ordinary mutexes 
 and @synchronized), which guarantees that no barrier is needed on the reader 
 side on the CPUs that run OS X and iOS. The expensive barrier on the reader 
 side is an acceptable trade-off because the writer path runs only once.
 
 
 -- 
 Greg Parker gpar...@apple.com Runtime Wrangler
 
 
 
 

Re: How to implement readonly property

2012-12-09 Thread Ken Thomases
On Dec 9, 2012, at 1:27 AM, Kyle Sluder wrote:

 If dispatch_once() really is unsuitable for use with a dispatch_once_t
 stored in Objective-C instance storage, then the correct example in the
 paper I've cited might be a sufficient workaround.

I thought we had established that, in all sane use cases, an instance variable 
once predicate is fine.  The cases where an instance variable once predicate 
would be unsafe are exactly the cases where it would be unsafe to access any 
instance variable, including the isa pointer.  So, if you're using the instance 
in any way, you've already assumed conditions that make the once predicate 
fine. (And, hopefully, you've more than assumed it, you've ensured it by proper 
inter-thread communication of the object pointer.)

Regards,
Ken


___

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


Re: How to implement readonly property

2012-12-09 Thread Kyle Sluder
On Dec 9, 2012, at 6:53 AM, Ken Thomases k...@codeweavers.com wrote:

 On Dec 9, 2012, at 1:27 AM, Kyle Sluder wrote:
 
 If dispatch_once() really is unsuitable for use with a dispatch_once_t
 stored in Objective-C instance storage, then the correct example in the
 paper I've cited might be a sufficient workaround.
 
 I thought we had established that, in all sane use cases, an instance 
 variable once predicate is fine.

Hence the hedge. ;-)

 The cases where an instance variable once predicate would be unsafe are 
 exactly the cases where it would be unsafe to access any instance variable, 
 including the isa pointer.  So, if you're using the instance in any way, 
 you've already assumed conditions that make the once predicate fine. (And, 
 hopefully, you've more than assumed it, you've ensured it by proper 
 inter-thread communication of the object pointer.)

Yes, but as Greg pointed out the real danger comes from not understanding all 
the nuances of this, and assuming that dispatch_once is a more powerful 
synchronization primitive than it really is.

--Kyle Sluder

___

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


Re: How to implement readonly property

2012-12-09 Thread Ken Thomases
On Dec 9, 2012, at 10:37 AM, Kyle Sluder wrote:

 On Dec 9, 2012, at 6:53 AM, Ken Thomases k...@codeweavers.com wrote:
 
 On Dec 9, 2012, at 1:27 AM, Kyle Sluder wrote:
 
 If dispatch_once() really is unsuitable for use with a dispatch_once_t
 stored in Objective-C instance storage, then the correct example in the
 paper I've cited might be a sufficient workaround.
 
 I thought we had established that, in all sane use cases, an instance 
 variable once predicate is fine.
 
 Hence the hedge. ;-)
 
 The cases where an instance variable once predicate would be unsafe are 
 exactly the cases where it would be unsafe to access any instance variable, 
 including the isa pointer.  So, if you're using the instance in any way, 
 you've already assumed conditions that make the once predicate fine. (And, 
 hopefully, you've more than assumed it, you've ensured it by proper 
 inter-thread communication of the object pointer.)
 
 Yes, but as Greg pointed out the real danger comes from not understanding all 
 the nuances of this, and assuming that dispatch_once is a more powerful 
 synchronization primitive than it really is.

I'm still not understanding the circumspection.  The use of dispatch_once() 
never _contributes_ to unsafe access.  It is unsafe if the situation is already 
unsafe.  If you try to avoid using dispatch_once() using other techniques like 
@synchronized(self), etc., that doesn't help anything.

Intellectually, I understand the concern that people will assume that 
dispatch_once() introduces safety where it doesn't, but as a practical matter 
I'm finding it hard to imagine a scenario where a) that comes up or b) avoiding 
dispatch_once() for some vague (to the naive developer) notion that it's unsafe 
would lead to better safety.  Can you or Greg illustrate with an example?

I feel that dispatch_once() with an instance variable once predicate _is_ the 
right answer for the class of problems where people would be tempted to use it 
and that we should be encouraging developers to rely on it rather than 
invariably worse alternatives.

Regards,
Ken


___

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