Alexander Sergeev's blog

Some thoughts on NSCache and NSDictionary

I have to work on a new projects with multiple concurrency issues.

During debugging this application I discovered and interesting thing about NSCache: it looks like NSCache retains and autorelease objects before pass them out (but NSDictionary does not):

// A possible objectForKey: implementation:
- (id)objectForKey:(id)key {
id obj = [self _getObjectForKey:key];
return [[obj retain] autorelease];
}

Why?

Apple declares NSCache a threadsafe class.

Consider the following situation:


NSCache * cache = ...;
// Thread A:
NSString * cachedString = [cache objectForKey:key1]; // point  A1
// do smth with a string:
NSLog(@"String value is %@", cachedString); // point A2

// Thread B:
 [cache removeObjectForKey:key1]; // point B1

 

Consider the processor executes  A1, then switches to B1 and returns to A2 after that.

In such a case we will have an invalid pointer to cachedString at point A2 (if we did not retain cachedString somewhere else).

But if objectForKey returns a retained-autoreleased value it is OK – the pointer is still valid (and it will remain valid until autorelease pool drain).

 

You may wish to retain-autorelease values while dealing with NSDictionary:

 

NSMutableDictionary * dict = ...;
// Thread A:
NSString * value = nil;
{ Lock lock(mutex);
value = [[[dict objectForKey:key1]retain]autorelease];
} // critical section ends
// do smth with a string:
NSLog(@"String value is %@", value);

// Thread B:
[dict removeObjectForKey:key1]; // point B1

 

 

Share

Category: IT

Tagged:

Leave a Reply

You must be logged in to post a comment.




Forgot?
Register
Facebook login by WP-FB-AutoConnect