Re: Lockless thread-safe accessor using blocks: how to?
Re: Lockless thread-safe accessor using blocks: how to?
- Subject: Re: Lockless thread-safe accessor using blocks: how to?
- From: WT <email@hidden>
- Date: Thu, 14 Apr 2011 14:26:02 -0300
On Apr 14, 2011, at 2:09 PM, David Duncan wrote:
> On Apr 14, 2011, at 10:02 AM, WT wrote:
>
>> I looked at dispatch_once() at one point, but I'm still confused by how it works.
>
> dispatch_once uses a predicate (just a flag) to determine if it should run the block or not. If that flag is false, then it sets the flag to true and executes the block. If the flag is true, it does nothing. What makes dispatch_once useful over a simple if statement is that it ensures that if you execute dispatch_once concurrently from multiple threads that flag gets updated exactly once, and the block gets called exactly once.
Thanks for explaining it, David. The bit that was throwing me off is the predicate part. I understand now that all I need is to declare a static variable of the appropriate type and pass a pointer to it to dispatch_once().
Here's another question, though. In the example I've mentioned already (reproduced below so you won't have to look it up in a previous message)
stSerialQueue is a static variable in the class where -shortStyleDateFormatter is declared.
shortStyleDateFormatter_ is an ivar in that same class, backing the property for which the accessor is being written.
WLT_GCDUtils' +dispatchToQueue: async: guarantees that the dispatch is deadlock-free regardless of which thread the block is executed in.
- (NSDateFormatter*) shortStyleDateFormatter;
{
[WLT_GCDUtils dispatchToQueue: stSerialQueue
async: NO
block:
^{
if (nil == shortStyleDateFormatter_)
{
shortStyleDateFormatter_ = [[NSDateFormatter alloc] init];
[shortStyleDateFormatter_ setLocale:
[NSLocale autoupdatingCurrentLocale]];
[shortStyleDateFormatter_ setDateStyle:
NSDateFormatterShortStyle];
}
}];
return shortStyleDateFormatter_;
}
// In WLT_GCDUtils.m
+ (void) dispatchToQueue: (dispatch_queue_t) queue
async: (BOOL) async
block: (void (^)(void)) block;
{
if (dispatch_get_current_queue() != queue)
{
if (async)
{
dispatch_async(queue, block);
}
else
{
dispatch_sync(queue, block);
}
}
else // already in target queue
{
// Just in case we might need one...
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
block();
[pool release];
}
}
the locale is autoupdating. The instance of the class in question listens to notifications of the locale changing, invokes a method that releases and nillifies all the ivars such as shortStyleDateFormatter_ when those notifications arrive, and then posts its own notification so that the rest of the application can update its UI. Naturally, the rest of the application may need to invoke -shortStyleDateFormatter and similar methods and the work needs to be redone for the new locale.
From my understanding of dispatch_once(), I can't use it for this purpose because it really executes the block only once in the application's life time.
WT_______________________________________________
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