On 21 Nov 2012, at 10:56, Andreas Grosam <agro...@onlinehome.de> 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 (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