• 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 Safely Invoke a Block
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How To Safely Invoke a Block


  • Subject: Re: How To Safely Invoke a Block
  • From: Ken Thomases <email@hidden>
  • Date: Wed, 21 Nov 2012 05:25:42 -0600

On Nov 21, 2012, at 5:09 AM, Tom Davie wrote:

> On 21 Nov 2012, at 10:56, Andreas Grosam <email@hidden> wrote:
>
>> I've defined a class Foo that defines a block via a property:
>>
>> @property (copy) void (^progressHandler)(RXProgressState progressState, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite);
>>
>> The property is synthesized by the compiler, ARC enabled.
>>
>> The block is usually invoked on a private thread for several times until an action finishes (an asynchronous NSURLConnection).
>> A client of class Foo should be able to set the block property at any time from any thread - that is it should also be able to set the block to NULL.  Now, I'm worried about thread safety.
>>
>> First, is it a good measurement to use a property with the "atomic" attribute?
>
> Not really, as your block may be released (by the setter) between getting the block and invoking it.

An atomic property's synthesized getter does the equivalent of retain plus autorelease.  So, the caller can rely on the received value staying valid for the current scope.
<https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW28>


> Grand Central Dispatch is your friend.
> @implementation MyClass
>
> static dispatch_once_t onceToken;
> static dispatch_queue_t dispatchQueue;
>
> typedef (void(^ProgressHandler)(RXProgressState progressState, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite);
>
> - (void)setProgressHandler:(ProgressHandler)progressHandler
> {
>    dispatch_once(&onceToken, ^
>    {
>        dispatchQueue = dispatch_queue_create("RXProgressQueue", DISPATCH_QUEUE_SERIAL);
>    });
>
>    dispatch_sync(dispatchQueue, ^()
>     {
>          if (_progressHandler != progressHandler)
>          {
>              [_progressHandler release];
>              _progressHandler = [progressHandler copy];
>          }
>     });
> }
>
> - (void)progressHandler
> {
>    return _progressHandler;
> }
>
> - (void)callSite
> {
>    …
>    dispatch_once(&onceToken, ^
>    {
>        dispatchQueue = dispatch_queue_create("RXProgressQueue", DISPATCH_QUEUE_SERIAL);
>    });
>    dispatch_sync(dispatchQueue, ^()
>     {
>         ProgressHandler handler = [self progressHandler];
>         handler(…);
>     });
>    …
> }

You are running the block within the dispatch_sync() block, meaning that the queue is monopolized for however long that runs.  That's likely undesirable and prone to deadlocks.

If you wanted to do something like this, you would declare 'handler' as __block outside of the dispatch_sync(), retrieve it with the dispatch_sync() block, and then call it after that returns.  ARC will ensure that it's retained by the implicitly-strong 'handler' variable.  However, that's overkill.

Regards,
Ken


_______________________________________________

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:
    • Image manipulation/composition library
      • From: "Rufat A. Abdullayev" <email@hidden>
References: 
 >How To Safely Invoke a Block (From: Andreas Grosam <email@hidden>)
 >Re: How To Safely Invoke a Block (From: Tom Davie <email@hidden>)

  • Prev by Date: Re: How To Safely Invoke a Block
  • Next by Date: Image manipulation/composition library
  • Previous by thread: Re: How To Safely Invoke a Block
  • Next by thread: Image manipulation/composition library
  • Index(es):
    • Date
    • Thread