Follow-up questions on sample class ThreadSafeQueue

Guenther Fuerthaller Guenther.Fuerthaller at onevision.com
Wed May 16 01:47:41 PDT 2007


well you should avoid confusing him.
runloops are for working with async streams.
in his situation he would rather need:

NSAutoReleasePool *pool = nil;
BOOL didRun = YES;
while (shouldKeepRunning && didRun) {
                 [pool release];
                 pool = [[NSAutoReleasePool alloc] init];
                element = [[[elements objectAtIndex:0] retain] 
autorelease];
// do something with your element and set didRun to NO if appropriate.
}
[pool release];

next question: why does it make sense to use
autorelease/autoreleasepool rather than retain/release?

guenther





Christiaan Hofman <cmhofman at gmail.com> 
Sent by: macosx-dev-bounces at omnigroup.com
16.05.2007 10:40

To
MacOSX-Dev List <macosx-dev at omnigroup.com>, Duncan Champney 
<duncanc at aol.com>
cc

Subject
Re: Follow-up questions on sample class ThreadSafeQueue







On 16 May 2007, at 2:32 AM, Duncan Champney wrote:

>
> On May 15, 2007, at 7:37 PM, Shawn Erickson wrote:
>
>> On 5/15/07, Duncan Champney <duncanc at aol.com> wrote:
>>> Chris,
>>>
>>> Thanks for the link to the ThreadSafeQueue post. It makes good sense
>>> to me to use NSConditionLock to manage shared access to a job queue.
>>>
>>> I have a couple of follow-up questions.
>>>
>>> I'm a little unclear on how the worker threads would use the
>>> ThreadSafeQueue. I would think the ThreadSafeQueue object's methods
>>> would run on the main thread, and the worker threads would call 
>>> those
>>> methods using performSelectorOnMainThread.
>>
>> Why do you think that? The whole point of the class is to allow
>> multiple threads to utilize the same queue directly. That is why it
>> uses NSConditionLock to protect the data structure it manages.
>
> Shawn,
>
> Thanks for the reply. I'm still trying to wrap my head around the 
> subtleties of multi-threading. I understand you now.
>
>>
>>> Also, I'm puzzled by a couple of lines in the method implementation.
>>> Why do the methods in -dequeue and -tryDequeue retain and 
>>> autorelease
>>> the object from "elements" in the same call. Here's the line from
>>> tryDequeue:
>>>
>>>        element = [[[elements objectAtIndex:0] retain] autorelease];
>>
>> That retains the objects and balances that retain with an 
>> autorelease.
>> That ensures that the object will continue to exist at least until
>> sometime in the future when the current autorelease pool is released
>> (drained).
>>
>> Why is this done? Well the removeObjectAtIndex: message could result
>> in the "element" object being deallocated because the elements array
>> could be the last object holding a retain on "element".
>>
>>> The retain and autorelease calls would seem to cancel each other 
>>> out.
>>
>> That is true but not immediately.
>>
>>> The retain call would increase the retain count for the object in
>>> "elements", and then the autorelease would immediately decrement it,
>>> for a net null effect.
>>
>> No autorelease doesn't immediately decrement the retain count. Review
>> the concept of NSAutoreleasePools.
>
> I just did what you suggested and read the description of 
> NSAutoreleasePool VERY carefully.
>
> The point I didn't understand before was that only an app's main 
> thread automatically releases objects in the autorelease pool (when 
> deallocating the autoreleasePool on the next pass through the event 
> loop.) Secondary threads don't release objects in their autorelease 
> pools automatically - they have to deallocate their autorelease 
> pools explicitly in order for the objects in the pool to be 
> released. Here's the relevant text:
>
>
>    NSAutoreleasePool objects are automatically created and 
> destroyed in the main thread of applications based on the 
> Application Kit, so your code normally does not  have to
>
>    deal with them. The Application Kit creates a pool at the 
> beginning of the event loop and releases it at the end, thereby 
> periodically releasing any autoreleased objects
>
>    generated while processing events.
>
>
> Thus when you execute the example statement I gave before
>
>    element = [[[elements objectAtIndex:0] retain] autorelease];
>
> from a secondary thread, the retain statement increments the retain 
> count, but the autorelease only adds the object to the autorlease 
> pool. Since the autorelease pool for a secondary thread isn't 
> deallocated automatically, the objects listed don't get balancing 
> release calls until the thread terminates or the autorelease pool 
> is deallocated.
>

Yes, that's why you should always create/release an autorelease pool 
on any secondary thread you create. For example by running the 
runloop on the secondary thread like this:

NSAutoReleasePool *pool = nil;
BOOL didRun = YES;
while (shouldKeepRunning && didRun) {
                 [pool release];
                 pool = [[NSAutoReleasePool alloc] init];
                 didRun = [NSAutoreleasePool currentRunLoop] 
runMode:NSDefaultRunnLoopMode beforeDate:[NSDate distantFuture];
}
[pool release];

Christiaan


_______________________________________________
MacOSX-dev mailing list
MacOSX-dev at omnigroup.com
http://www.omnigroup.com/mailman/listinfo/macosx-dev




More information about the MacOSX-dev mailing list