Is NSIndexPath threadsafe? Is NSIndexPath threadsafe? multithreading multithreading

Is NSIndexPath threadsafe?


So far the best answer I have is as I suspect:

As of OS X 10.7 and iOS 5, NSIndexPath is thread safe. Prior to that, instances are thread safe because they are immutable, but the shared retrieval of existing instances is not.

To my method which returns index paths on-demand, I did this:

- (NSIndexPath *)indexPath;{    NSIndexPath *result = … // create the path as appropriate    return [[result retain] autorelease];}

Since implementing that last line of code, we've had no more crash reports from index paths.

The index paths are created by -indexPathByAddingIndex: or +indexPathWithIndex:.

The results I am seeing make me pretty certain that (prior to 10.7/iOS5) these methods are returning an existing NSIndexPath instance. That instance is not retained by the current thread in any way though, so the thread which first created the instance (main in our case) is releasing the path (likely through popping the autorelease pool) and leaving our worker thread with a dangling pointer, which crashes when used, as seen in the question.

It's all a bit terrifying, because if my analysis is correct, the retain/autorelease dance I've added is simply replacing one race condition with another, less-likely one.

Prior to 10.7/iOS5, I can think of only one true workaround: Limit all creation of index paths to the main thread. That could be rather slow if such code gets called a lot, so could be improved — at the cost of memory — by maintaining some kind of instance cache of your own for background threads to use. If the cache is retaining a path, then you know it won't be deallocated by the main thread.


Apple don't specifically list NSIndexPath as thread safe, but they do say that immutable classes are generally safe and mutable ones generally aren't. Since NSIndexPath is immutable it's safe to assume it's thread safe.

But "thread safe" doesn't mean that it can't cause crashes by being released by one thread before you use it on another though. Thread safe generally just means that its mutator methods contain locking to prevent glitches due to two threads setting properties concurrently (which is why classes without mutator methods are generally thread safe, although lazy getters and shared instances can also cause problems).

It sounds like your bug is more likely due to using an autorelease pool or some other mechanism that causes your object to be released at a time outside your control. You should probably ensure that any concurrently accessed objects are stored in properties of long-lived classes so that you can control their lifespan.

Creating an autoreleased object and accessing it from another thread after you've removed all strong references to it is a dangerous racing game that is likely to cause hard-to-trace crashes regardless of whether the object in question is "thread safe".