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: Glen Low <email@hidden>
- Date: Tue, 16 Mar 2004 14:20:13 +0800
On 16/03/2004, at 9:16 AM, Dustin Voss wrote:
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.
In the documentation for performSelectorOnMainThread it says: "Note
that you cannot cancel this perform request, unlike with the timed
perform requests such as performSelector:withObject:afterDelay:".
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.
There is one flaw in that 4 might deadlock the thread if it is called
by the thread and not by the original object in the main thread.
Silly me. Reading the documentation for detachNewThreadSelector:, it
says, "The objects aTarget and anArgument are retained during the
execution of the detached thread, then released." So since my object
spawns a thread on my object's selector, and sends
performSelectorOnMainThread to the object, then the object lifetime
must be extended to the last of (1) any client retains of the object,
(2) the end of the thread or (3) the end of last scheduled
performSelector. Exactly what I need!
I still have the chicken-and-egg problem of when to send the kill
message though.
Cheers, Glen Low
---
pixelglow software | simply brilliant stuff
www.pixelglow.com
_______________________________________________
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.