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]

Reply via email to