Re: retainCount
Re: retainCount
- Subject: Re: retainCount
- From: Brant Vasilieff <email@hidden>
- Date: Fri, 5 Oct 2001 20:14:09 -0700
On Friday, October 5, 2001, at 07:06 PM, cocoa-dev-
email@hidden wrote:
So, from the different posts on the subject, it seems there is no way
to tell whether an object is in the autorelease pool or not? This
seems like a shortcoming. I'd even try using +showAllPools, then
searching the output to see if my object is in there, except there
seems to be no way to get the output.
After all the replies to the various questions concerning autorelease
pools, and retain counts, I'm amazed at your continued insistence on
avoiding them.
If you know enough about the internals of an object to know that you
want to remove it from an autorelease pool, then don't put it there to
begin with. There is no list of pools. Each thread can create their
own pool and pools can be nested. It is unsafe to remove an item from a
pool. Prematurely clearing a pool would wreak havoc all the way up the
call chain.
Autorelease pools are not thread safe. Adding an item to the pool is
only atomic within the thread that own it. If you had a multi-threaded
app, and could iterate a release pool from another thread to see if an
item existed, you could be interrupted before acting on that knowledge
allowing the pool to be released, in which case the object technically
wouldn't exist in the pool any more. Even though your test would assume
it was.
If you look at the interface for the autorelease pool, you'll wee it
doesn't use an NSArray.
@interface NSAutoreleasePool : NSObject {
@private
void *_token;
void *_reserved3;
void *_reserved2;
void *_reserved;
}
+ (void)addObject:(id)anObject;
- (void)addObject:(id)anObject;
_token is most likely some form of linked list or linked buffer.
Further, in thread conditions, autorelease is your friend. Trust me.
If you ask a Person object to return their name, that object cold be
released before you get the result. To fix that, you return an
autoreleased version of it. Either by retain/autorelease or
copy/autorelease;
For example:
- (void)dealloc
{
[name release];
[super dealloc];
}
- (NSString*)name
{
return [[name retain] autorelease];
}
- (void)setName:(NSString*)inName
{
id oldName = name;
name = [inName copy];
[oldName release];
}
- (id)initWithName:(NSString*)inName
{
self = [super init];
{
name = [inName copy];
}
return self;
}
Thread A:
- (void)sayHiToPerson:(Person)*inPerson
A1: {
A2: NSString* name = [inPerson name];
A3: NSLog(@"Hi %@.", name];
A4: }
Thread B:
- (void)giveDoctorateToPerson:(Person*)inPerson
B1: {
B2: NSString* name = [inPerson name];
B3: name = [NSString stringWithformat:@"Dr. %@", name];
B4: [inPerson setName:name];
B4: }
Thread A could end up allowing Thread B to execute between A2 and A3.
If -[Person name] didn't return a retained and autoreleased version of
name, and instead just return the pointer to name, then name could be
deallocated by thread B, before we get to log the name.
Don't avoid using autorelease pools, embrace them.
HTH,
Brant