Boost logo

Threads-Devel :

From: David Abrahams (dave_at_[hidden])
Date: 2006-03-06 17:48:06


Matt Hurd <matt.hurd_at_[hidden]> writes:

>> > A common structure we should support to prevent deadlocks is the
>> > idea of a group of mutexes for simulataneous locking. Deadlock is
>> > guaranteed not to occur if they are always accessed in the same
>> > order. Enforcement of ordered access will prevent deadlock, a noble
>> > goal.
>>
>> Sure, although it isn't always the best way. I recently put together
>> an example of deadlock prevention using ordered access. I was
>> surprised at the complexity of the resulting locking strategy required
>> (see enclosed). A loop around a pair of locking attempts with an
>> intervening unlocked section was required in order to make it work; it
>> reminded me of some of those lock-free algorithms. It was suggested to
>> me that it would have been cleaner to use timed locks (actually
>> try-locks sound better to me now, but I'm not a threading expert),
>> since I needed a loop anyway; then you can lock in any order and just
>> come back and try again if a deadlock would have occurred. It would
>> have saved the two-phase locking dance I do in the code.
>
> I had a look at the code. The use case wasn't clear to me. What is the
> locking trying to protect and what is decouple for?

It's a simple subject/observer pattern. The collaborators can be
coupled, in which case they'll communicate with one another, and
decoupled, in which case they won't.

> A basic safe partnering might look this this:
>
> void switch_and_report(collab* new_partner)
> {
> // gates must be locked

There's the rub. They have to be locked in the right order or you
could deadlock.

> synco() << "partnered " << this << " with " << new_partner << std::endl;
> this->partner = new_partner;
> new_partner->partner = this;
> }
>
> void couple(collab* new_partner)
> {
> if (new_partner == this) {
> boost::mutex::scoped_lock lk(gate);
> switch_and_report(new_partner);
> } else {
> lockpair<mutex> lk (gate, new_partner->gate);
> switch_and_report(new_partner);

No, you need to decouple all participants, including the current
partners of *new_partner and *this.

> }
> }
>
> But I'm clearly missing the point of your algorithm. If you explain
> the use case I'll have a crack at it with the real use in mind.

Just make the example code run without deadlock.

> If you want the lock to outlive the collaboration acquisition then
> your locking has to live over the life of the acquisition unless it
> is up to the acquisition to free itself after doing work. Perhaps
> that is what decouple is about??

It's very simple: decouple is about disconnecting a pair of
collaborators.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

Threads-Devel list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk