• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Autorelease and passing by reference in background threads
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Autorelease and passing by reference in background threads


  • Subject: Re: Autorelease and passing by reference in background threads
  • From: Greg Parker <email@hidden>
  • Date: Mon, 27 Apr 2009 15:02:54 -0700

On Apr 27, 2009, at 12:17 PM, Symphonik wrote:
I am using a couple of methods that use NSError ** pointers to communicate error conditions. These methods run on background threads and so have their own autorelease pools set up. I pass an NSError pointer down a couple of method calls -- by the time it comes back up, it has been dealloc'd by the autorelease pool.

[...]

- (void)runSomethingThatWillFail:(NSError **)error {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/BOGUS" error:error];
[*error retain];
[pool release];
[*error autorelease];
}


Now it works and isn't leaking anymore. But factor in that I have to do some checking on the existence of the error before I dereference it, etc... this is becoming some ugly code just to get my NSError back up the chain.

Am I overthinking this? Anyone else have better suggestions?

That is the correct way to handle an autoreleased object that crosses a pool boundary; you would need to do the same thing with an ordinary autoreleased return value too. The best way to simplify your code and avoid typos is to wrap the *error handling and pool release in a single #define.


    #define RELEASE_POOL_KEEP_ERROR (pool, error)         \
        do {                                              \
            if (error) [*error retain];       \
            [pool release];                               \
            if (error) [*error autorelease];  \
        } while (0)

I'm confused about one part of your description. You say that these methods have autorelease pools because they run on background threads. But either there's another autorelease pool set up outside here, in which case you don't need the local pool after all, or [*error autorelease] is a leak. The leak might be the kind that logs "autorelease with no autorelease pool" to the console, or the kind where there is a pool in place but it's immortal. Also, if you intend to pass that error object back to some other calling thread then you will need code to keep the object alive other than the background thread's autorelease pool; otherwise you crash when the background thread's autorelease pool is drained before the other thread retains the error for itself.


There is one alternative to the retain/autorelease dance, sometimes: don't drain your pool at all.


- (void)runSomethingThatWillFail:(NSError **)error {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/BOGUS" error:error];
if (!(error && *error)) [pool release];
}


This version lets the pool live if there is an error. It works because autorelease pools are nested: whenever any autorelease pool is destroyed, all pools created after it are also destroyed. So as long as there's some other pool outside this one, and that outer pool is expected to be drained soon enough that you don't care about letting everything in your pool live longer, then it's safe to simply drop your pool on the floor and let it be cleaned up later.

This fallback cleanup of autorelease pools is intended for exception handling: the thrown object is autoreleased, and intervening pools between the throw and the catch are ignored until later. I see no reason why it couldn't be used for NSErrors too.
http://sealiesoftware.com/blog/archive/2008/09/16/objc_explain_Exceptions_and_autorelease_pools.html



-- Greg Parker email@hidden Runtime Wrangler


_______________________________________________

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


References: 
 >Autorelease and passing by reference in background threads (From: Symphonik <email@hidden>)

  • Prev by Date: Re: Autorelease and passing by reference in background threads
  • Next by Date: Re: 10.4.x install for testing...
  • Previous by thread: Autorelease and passing by reference in background threads
  • Next by thread: Re: Autorelease and passing by reference in background threads
  • Index(es):
    • Date
    • Thread