
On Tue, 06 Nov 2007 12:40:40 +0000, Phil Endecott wrote:
Anthony Williams wrote:
The interruption points are:
thread::join, thread::timed_join this_thread::sleep condition_variable::wait, condition_variable::timed_wait condition_variable_any::wait, condition_variable_any::timed_wait this_thread::interruption_point
Am I the only one who thinks that not having cancellation points at blocking I/O makes this fairly useless? Perhaps I am! I'm curious to hear about use-cases where Anthony or Preston's proposals are appropriate.
I have a use case in my own app for an interruptable lock and condition. Though being able to interrupt a sleep would also be cool. The use case is, I have multiple messages going through my system, they have a pre-determined path. I want to be able to interrupt them if they are blocked, and do things like re-route them, hold them, drop them, or invoke a specific function call on them in the thread that currently owns the message. To do this each message is given a UUID, and (using my own version's idioms) an interruptable_pred. As the message goes through its path, along the way it goes through both conditions and mutexes where it must be interrupted. To facilitate this, all mutexes it will wait on in its path are interruptable_mutexes. The interruptable_pred is updated along the way (set when we are going to lock, unset when we have got the lock). This way, I can do something like this: boost::shared_ptr<message> m = message::find(uuid); m->interrupt_drop(); And the mutex it is waiting on will be interrupted (an exception thrown) and the message will be dropped. Actually, to make things work cleaner, I have actually implemented into my interruptable_pred a boost::function callback. So that if the callback is defined, it will be called, otherwise an exception will be thrown (the idea being that function can throw the exception if it REALLY wants to interrupt). So in my above implementation - on interrupt, it will interrupt the mutex (see my previous email on how that works), call a function, which will change some internal state of the message object and then throw an exception. Thereby enabling me to control my message as it goes through the system, even if it is in condition waits or mutex locks. Even if I have no control over the duration a lock is held (as long as they use an interruptable mutex).
One application for cancellation is to cleanly kill off threads or groups of threads when something goes wrong. For example, I may observe no activity and assume that a deadlock has occurred. This would require that lock-acquisition be a cancellation point.
Yes, this is another purpose I had for this, was breaking a deadlock. I've long wanted a way to do this without pthread_cancel, which is very dirty. And an interruptable mutex would be ideal for this.
I think that, even if this problem could be avoided, delivering a signal to the right thread is very hard. There used to be a pthread_kill() function equivalent to the regular kill () function in posix. I don't see it anymore. Maybe I immagined it ;)
Can I suggest that we don't entirely forget about 3) use pthread_cancel
It has some disadvantages, but it's the only solution that offers cancellation at blocking I/O.
Yah, but pthread_cancel is more or less a kill -9 of the thread. All resources are left dangling in the wind, no destructors are called, and more or less you are in a Bad Situation (tm). Interrupting a lock is a much preferred method. PreZ :)