Hi David, thanks for pitching in.
On Apr 14, 2011, at 1:40 PM, David Duncan wrote: >> I tested this out before replying as I wasn't 100% certain. It may be that >> we have misunderstood each other somehow, but the following code (in a clean >> new project) was what I used to confirm to myself that two >> concurrently-executing threads have independent instances of the variable: >> http://www.dur.ac.uk/j.m.taylor/block_test_code.m > > On this point Jonathan is correct. What __block does is ensure that a > declared variable has the ability to survive its stack frame, not that a > variable of that name is shared with all invocations of that stack frame. If > you want a variable that will be shared with all instances of that stack > frame, you want the "static" qualifier. I see. It's final, then: I have misunderstood the documentation. Thank you both for pointing me in the right direction. >>>> However I don't think you should need to do this anyway. I would change >>>> your code to something like this: >>>> >>>> - (SomeObjType) foo >>>> { >>>> dispatch_sync(queue, >>>> ^{ >>>> // Code in this block ensures bah is valid >>>> if (nil == bah) >>>> { >>>> // Code to compute and store bah goes here >>>> } >>>> }); >>>> >>>> return bah; >>>> } > > > Fundamentally however, this will not work. If you want to do lazy > initialization of a variable with thread safety then you should use > dispatch_once() to initialize the variable. This is also not something you > can do with a __block or static variable (unless you want all instances to > have the same value, which seems to be against the way you've declared the > method). Basically you need to do this: > > - (SomeObjectType) foo > { > dispatch_once(&ivar_predicate, ^ { ivar_value = /* initialization */ }); > return ivar_value; > } I looked at dispatch_once() at one point, but I'm still confused by how it works. In any case, here's an actual example of where I use the pattern Jonathan suggested, and I can't see why it would not work. 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]; } } Thanks again for your help. WT_______________________________________________ Cocoa-dev mailing list ([email protected]) 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to [email protected]
