• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: How to implement readonly property
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to implement readonly property


  • Subject: Re: How to implement readonly property
  • From: Richard Heard <email@hidden>
  • Date: Sat, 08 Dec 2012 17:27:53 -0800

Greg,

So, from what you are saying, either of these snippets should be valid, right?

> +(id)sharedInstance{
>     static id _sharedInstance = nil;
>
>     if (!_sharedInstance){
>         @synchronized([self class]){
>             if (!_sharedInstance){
>                 id sharedInstance = [[super allocWithZone:NULL] init];
>                 OSMemoryBarrier();
>                 _sharedInstance = sharedInstance;
>             }
>         }
>     }
>
>     OSMemoryBarrier();
>     return _sharedInstance;
> }

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 <email@hidden> wrote:

> On Dec 8, 2012, at 11:17 AM, Steve Sisak <email@hidden> wrote:
>> At 10:24 AM -0800 12/8/12, Kyle Sluder wrote:
>>> On Dec 8, 2012, at 10:06 AM, Steve Sisak <email@hidden> 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     email@hidden     Runtime Wrangler
>
>
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> 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:
>
> This email sent to email@hidden

_______________________________________________

Cocoa-dev mailing list (email@hidden)

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:

This email sent to email@hidden

  • Follow-Ups:
    • Re: How to implement readonly property
      • From: Jean-Daniel Dupas <email@hidden>
    • Re: How to implement readonly property
      • From: Kyle Sluder <email@hidden>
    • Re: How to implement readonly property
      • From: Greg Parker <email@hidden>
References: 
 >Re: How to implement readonly property (From: Steve Sisak <email@hidden>)
 >Re: How to implement readonly property (From: Ken Thomases <email@hidden>)
 >Re: How to implement readonly property (From: Steve Sisak <email@hidden>)
 >Re: How to implement readonly property (From: Marco S Hyman <email@hidden>)
 >Re: How to implement readonly property (From: Kyle Sluder <email@hidden>)
 >Re: How to implement readonly property (From: Steve Sisak <email@hidden>)
 >Re: How to implement readonly property (From: Kyle Sluder <email@hidden>)
 >Re: How to implement readonly property (From: Steve Sisak <email@hidden>)
 >Re: How to implement readonly property (From: Greg Parker <email@hidden>)

  • Prev by Date: Re: How to implement readonly property
  • Next by Date: Re: How to implement readonly property
  • Previous by thread: Re: How to implement readonly property
  • Next by thread: Re: How to implement readonly property
  • Index(es):
    • Date
    • Thread