• 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: Tom Davie <email@hidden>
  • Date: Wed, 21 Nov 2012 11:09:35 +0000

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.

> Secondly, I'm invoking the block as follows (from within a NSURLConnectionDelegate method):
>
>    progress_handler_block_t block;
>    if ( (block=self.progressHandler) != NULL) {
>        block(RXProgressStateStart, 0, self.source.size);
>    }
>
>
> since it appears to me, that
>
>    if (_progressHandler) {
>        _progressHandler(RXProgressStateStart, 0, self.source.size);
>    }
>
> or
>
>    if (self.progressHandler) {
>        self.progressHandler(RXProgressStateStart, 0, self.source.size);
>    }
>
> isn't thread safe.
>
>
> Your comments are welcome!

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(…);
     });
    …
}

Tom Davie
_______________________________________________

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 Safely Invoke a Block
      • From: Ken Thomases <email@hidden>
References: 
 >How To Safely Invoke a Block (From: Andreas Grosam <email@hidden>)

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