views:

172

answers:

3

Hi

I am trying to determine if an object is valid. The program has (at least) two threads and one of the threads might invalidate the object by removing it from an NSMutableArray. I need the other thread to check either its existence or validity before acting on it.

A: 

You say

I need the other thread to check either its existence or validity before acting on it.

The easiest way is to hold on to the index of the object in the NSMutableArray and then do the following

if( myObject == [myArray objectAtIndex: myObjectIndex] ) {

   // everything is good !
}
else {
   // my object is not what I think it is anymore
}

There are clear problem with this approach however

  1. insertion, and deletion will stuff you up
  2. The approach is not thread safe since the array can be changed while you are reading it

I really recomend using a different way to share this array between the two threads. Does it have to be mutable? If it doesn't then make it immutable and then you no longer have to worry about the threading issues. If it does, then you really have to reconsider your approach. Hopefully someone can give an cocoa way of doing this in a thread safe way as I don't have the experience.

hhafez
This totally non-thread safe. In between checking for the pointer and dereferencing it could be removed, and it could crashing inside the array calls anyway since NSArray is not internally threadsafe and mutating it from one thread while it is being read can result it a crash.
Louis Gerbarg
I agree with your comment, I'll add it to my answer
hhafez
I wonder if it makes a difference asking if it's *invalid* vs asking if it's *valid. Perhaps I'm thinking too deeply?
John Smith
+2  A: 

You can't. The only way to check if the memory your object pointer has still represents a valid object is to dereference it, but dereferencing an "invalid" object (by which I assume you mean one that has been dealloced) will result in either accessing the memory of a new object that has been allocated in the same location, garbage data that may or may not be identical to a normal object, or an unmapped memory page that will result in an immediate EXEC_BAD_ACCESS.

Any time you are holding a reference to an object you might use in the future you must retain it. If you don't you have not shown any interest or ownership in the object and the system may throw it away at any time.

Using objective C accessors and properties instead of directly setting ivars and using retain/release simplifies doing the right thing quite a bit.

Louis Gerbarg
I don't really have the choice to retain it. One of the threads is just an observer and should not interact with the objects.
John Smith
A: 

Multi-threaded programming is hard. Hard does not begin to capture how difficult it is. This is the kind of hard in which a general, useable, 'reasonably qualified' way of deterministically adding two different numbers together that are being mutated and shared by multiple threads in bounded time without the use of any special assistance from the CPU in the form of atomic instructions would be a major breakthrough and the thesis of your PhD. A deity of your choice would publicly thank you for your contribution to humanity. Just for adding two numbers together. Actually, multi-threaded programming is even harder than that.

Take a look at: Technical Note TN2059 Using collection classes safely with multithreaded applications. It covers this topic in general, and outlines some of the non-obvious pitfalls that await you.

johne