RE: [boost] Re: Boost.Threads: Do we need all those mutexes?

From: Howard Hinnant [mailto:hinnant@twcny.rr.com]
On Jul 9, 2004, at 4:11 PM, Peter Dimov wrote:
rw_mutex m;
void invitation_for_deadlock() { read_lock r(m); // ok to read upgradable_read_lock ur(m); r.unlock(); write_lock w(ur); // ok to write }
It took me awhile to spot the deadlock in the above code. Does anyone else see the above code as scary? (scary as in looks ok but isn't). Or is the deadlock obvious to everyone else (and thus not scary)?
Not scary, IMO, even if not obvious, because it always deadlocks, as soon as you attempt the "idiom". You can't miss it.
I'm not following "always deadlocks". If only one thread enters, at what point does it deadlock (assuming no other thread playing with m)? Experimentally running through this on my prototype implementation with a single thread isn't deadlocking. But perhaps my prototype is buggy?
It only deadlocks under a race, but I'm not sure it's scary. It's something I'm use to seeing in the presents of r/w locks. I don't know where you left off, are you implementing single upgradeable or multiple upgradeables? If only one upgradeable can exist in the system at a time then, what would deadlock, will result in a failure to create a second upgradable lock, IIUC. You can always manufacture ways to deadlock, I'd still vote for just hanging a try/timed_promote() on all read locks. Unless perhaps there's overhead in upgradable_read_lock that isn't required in read_lock? Glen

On Jul 9, 2004, at 6:54 PM, Glen Knowles wrote:
From: Howard Hinnant [mailto:hinnant@twcny.rr.com]
On Jul 9, 2004, at 4:11 PM, Peter Dimov wrote:
rw_mutex m;
void invitation_for_deadlock() { read_lock r(m); // ok to read upgradable_read_lock ur(m); r.unlock(); write_lock w(ur); // ok to write }
It took me awhile to spot the deadlock in the above code. Does anyone else see the above code as scary? (scary as in looks ok but isn't). Or is the deadlock obvious to everyone else (and thus not scary)?
Not scary, IMO, even if not obvious, because it always deadlocks, as soon as you attempt the "idiom". You can't miss it.
I'm not following "always deadlocks". If only one thread enters, at what point does it deadlock (assuming no other thread playing with m)? Experimentally running through this on my prototype implementation with a single thread isn't deadlocking. But perhaps my prototype is buggy?
It only deadlocks under a race, but I'm not sure it's scary. It's something I'm use to seeing in the presents of r/w locks.
If r/w locks regularly encourage deadlocks, I am not anxious to further pursue them. I'm not convinced of that however (and hope I won't be). I'm seeking a system which makes it easy to avoid deadlocks, race conditions, and leaked locks. Admittedly any system can be abused. But a good system will naturally reduce accidental abuse, while not necessarily preventing intentional abuse.
I don't know where you left off, are you implementing single upgradeable or multiple upgradeables? If only one upgradeable can exist in the system at a time then, what would deadlock, will result in a failure to create a second upgradable lock, IIUC.
Single upgradable.
You can always manufacture ways to deadlock, I'd still vote for just hanging a try/timed_promote() on all read locks. Unless perhaps there's overhead in upgradable_read_lock that isn't required in read_lock?
There's not overhead in the lock, but in the rw_mutex to support both read/write and upgradable_read. But hanging a try_promote on multiple upgradable read locks really makes me nervous. Doing so (imho) makes deadlock significantly more likely (see my post with lock_both/transfer_lock example). Fwiw, here's what I'm seeing that is scaring me: rw_mutex m; void invitation_for_deadlock() { // 1 read_lock r(m); // ok to read // 2 upgradable_read_lock ur(m); // 3 r.unlock(); // 4 write_lock w(ur); // 5 // ok to write } Thread A Thread B 1 2 3 4 1 2 A holds ur. B holds r. A waits for B to unlock r so it can unlock ur and lock w. B waits for A to unlock ur so it can lock ur. -Howard
participants (2)
-
Glen Knowles
-
Howard Hinnant