Re: Safely terminating a thread, or the dealloc that doesn't dealloc?
Re: Safely terminating a thread, or the dealloc that doesn't dealloc?
- Subject: Re: Safely terminating a thread, or the dealloc that doesn't dealloc?
- From: Dustin Voss <email@hidden>
- Date: Mon, 15 Mar 2004 17:16:00 -0800
On 15 Mar, 2004, at 4:17 PM, Glen Low wrote:
On 16/03/2004, at 6:31 AM, Dustin Voss wrote:
If your object is being deallocated, I assume it doesn't actually
want to deal with any further messages from the thread. Have you
tried calling [NSObject cancelPreviousPerformRequestsWithTarget:
self] in your -dealloc method? That might get rid of any requests
posted from another thread.
I'm not sure cancelPreviousPerformRequestsWithTarget:self: is
qualified to work with performSelectorOnMainThread, it works with the
delay version of performSelector. In any case this doesn't solve the
problem, since without mutexing the code, the thread might schedule
more performSelectorOnMainThreads *after* my object dealloc cancels
the rest.
Well, it is worth a try. I think all the performs use the same
mechanism. And after the thread gets the "kill me" notice, it should
not schedule any more main-thread performs. You can make the "kill me"
notice atomic without difficulty, preventing any synchronization issues
there.
If your object does want to finish up with the thread's business, I
don't think the -dealloc method is the place to do that. You could
try pushing back up the chain of command: have the owner of the
object call a -doneWithPendingBusiness method and not call the final
-release if there's something your object still needs to do.
I didn't like the idea because it complicates the object use, the
client has to say "doneWithPendingBusiness" explicitly instead of just
release -- and perhaps the client doesn't know that it is the last
reference to the object etc.
Yeah, I don't like it either. This technique usually doesn't work out
well for me.
Another possibility is to override -release in your object to delay
performing -dealloc until the thread's business is taken care of.
This seems cleaner than your thought #1, because until -dealloc is
called, the object is still theoretically capable of being retained
and saved from death. The implementation might be tricky, though.
I thought about this:
1. On object init, I do a retain and spawn the thread.
2. The thread is a loop that when it ends, schedules a release on the
object, so retain and release are balanced.
3. Now sane client code will never cause retainCount to drop to zero
and dealloc the object.
4. I override the release method so that when retainCount == 1, I send
the kill message to the thread.
5. When the thread receives the kill message it drops out of the loop,
and schedules a release on the object.
6. Because the pending performs are serialized, any such pending
performs are handled by the object.
7. Finally the object receives the last message, which is the
scheduled release, and it gets dealloc'ed.
The only flaw I can see is if at stage 6, a client tries to retain the
object again (in response to actioning a perform), then the scheduled
release doesn't dealloc the object as expected -- but now the thread
is gone!!
It looks somewhat tricky, but I'm not sure I can do better without
mutexing or blocking.
Sounds good. The flaw is not really a flaw, since the client should
know the object is going away and can't accept any more work. The fact
that the object is technically still around cleaning up loose ends
ought to be irrelevant.
If you want the object to hang around waiting for more work, I think
you'll have to give it a more independent lifetime.
(Yes, I'm rampantly anthropomorphizing. Deal.)
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.