Submission for boost::thread - interruptable_mutex

Hi, I have written a refinement on boost::mutex that allows for it to be interrupted while waiting to acquire the mutex by altering a predicate (once the mutex is acquired, it acts like a regular mutex). Here is the code: http://www.neuromancy.net/fisheye/browse/mantra/trunk/Mantra-I/mantra/utils/... It has been fully unit tested. The idea is simple, using an interruptable_mutex operates exactly like a boost::mutex normally, so boost::interruptable_mutex mtx; { boost::interruptable_mutex::scoped_lock sl(mtx); ... } All fine. However, if you want the ability to be able to interrupt the mutex while blocked waiting to acquire, you could do: boost::interruptable_mutex mtx; boost::interruptable_pred pred(mtx); { boost::interruptable_pred::scoped_lock sl(pred); ... } Then in another thread, I could call: pred(true); and it will throw an exception in the thread waiting to acquire the scoped_lock. This works when waiting on reacquisition of a lock after a condition just as well, eg: { boost::interruptable_pred::scoped_lock sl(pred); ... boost::condition cond; cond.wait(sl); // Assuming we got signaled, we would reacquire sl, however if // multiple threads were trying to acquire sl, we could block // waiting for the lock re-acquisition, that is breakable. } In addition to this, the implementation I have allows you to register a callback function that will be invoked in place of just throwing an exception. The reason the interruptable_pred is a separate class is that you may want multiple predicates associated with the same lock. For example a situation where the lock is for a queue, and you are pushing multiple messages to that queue. Each message would have a interruptable_pred created for it, but constructed with the same interruptable_mutex, the one guarding the queue. This way you can interrupt the lock acquire for a single message only without interrupting others also waiting. As with all my submissions, do with it as you please. I have unit tested it, and it works here. I just don't believe this should be submitted as a separate component, but more folded into boost::thread. PreZ :)

"Preston A. Elder" <prez@neuromancy.net> writes:
I have written a refinement on boost::mutex that allows for it to be interrupted while waiting to acquire the mutex by altering a predicate (once the mutex is acquired, it acts like a regular mutex).
Here is the code: http://www.neuromancy.net/fisheye/browse/mantra/trunk/Mantra-I/mantra/utils/...
It's an interesting idea. I'm yet to be convinced that it's worth adding to boost.thread, though --- I'd rather just use a condition variable. Anthony -- Anthony Williams Just Software Solutions Ltd - http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL

On Thu, 25 Oct 2007 17:53:05 +0100, Anthony Williams wrote:
"Preston A. Elder" <prez@neuromancy.net> writes:
I have written a refinement on boost::mutex that allows for it to be interrupted while waiting to acquire the mutex by altering a predicate (once the mutex is acquired, it acts like a regular mutex).
Here is the code: http://www.neuromancy.net/fisheye/browse/mantra/trunk/Mantra-I/mantra/ utils/interruptable_mutex.h?r=419
It's an interesting idea. I'm yet to be convinced that it's worth adding to boost.thread, though --- I'd rather just use a condition variable.
Anthony
Well, in one respect, the interface I provide is just a nice way of not forcing the end-user to write a condition themselves. But its more than that. If you recall the situation I said earlier, where you do: interruptable_pred pred(mtx); cond.wait(pred); Assuming you do a similar thing in multiple threads, so you have multiple threads each with their own predicate object (which in turn is referencing the same mutex), and they wait on the same condition. Then I do this: cond.notify_all(); All threads will break out of the condition wait, and be waiting on the same mutex, one will acquire the mutex the others block. The above code using my interruptable_mutex/pred makes this no problem, I can still modify my predicate and break out. Using a hand-crafted mutex and condition to simulate an interruptable_mutex/pred presents two problems: 1) I can't pass a condition to another condition, so there is no way to have some kind of separate interruption (which is what a pred is). So there is no way to just signal the condition to stop waiting for the re- acquire of the lock after using that lock in another condition. 2) Because of this, you pass the mutex to the condition. When the condition exits wait state, it is trying to acquire the lock, and blocked on a mutex::do_lock(). There is no way to interrupt this. Plus, the big problem with just using a condition is this: boost::mutex::scoped_lock sl(mtx); if (cond.wait(sl)) { ... } You have already blocked trying to acquire the mutex, before you ever hit the condition wait. Plus, even DO the condition wait if you have already got the lock, unless you are proposing: // somewhere else, these are the lock and condition protecting a queue<> // or whatever. boost::try_mutex mtx; boost::condition cond; // In my code where I must wait on the condition, say pushing onto a // queue<>. boost::mutex mylock; bool breakout; boost::try_mutex::scoped_try_lock sl(mtx); while (!sl.locked()) { boost::mutex::scoped_lock tmplock(mylock); cond.wait(mylock); if (breakout) throw std::runtime_exception("Broken out!"); tmplock.unlock(); sl.try_lock(); } and then elsewhere I decide I want to interrupt the thread blocked waiting for the queue<>'s lock, so from another thread I do: boost::mutex::scoped_lock sl(mylock); breakout = true; cond.notify_all(); sl.unlock(); This will achieve the interruptable mutex semantics I wrote I guess, but still will not work inside a condition, and is a lot of ugly code to use every time you want to be able to interrupt your lock. Preston
participants (2)
-
Anthony Williams
-
Preston A. Elder