
Howard Hinnant <hinnant <at> twcny.rr.com> writes:
My take, depending upon how the w(r) constructor is implemented, is either:
1. deadlock. 2. one thread blocks and one thread gets the lock.
Imho choice 1 is a buggy implementation of the w(r) constructor.
Yes, there's no point creating a library facility that assists you in writing code that deadlocks.
And choice 2 results in the assert(x==y) possibly firing.
I think that in the second case, an exception should be thrown. Typically, if you fail to promote a rw lock from read to write, then you will have to repeat the part of the code that was read-protected after the other thread's write lock has been released: bool try_sale(rw_mutex& m) { read_lock rl(m); long balance = get_balance(); long cost = get_total_cost(); if (balance > cost) { write_lock wl(rl); set_balance(balance - cost); // ... return true; } return false } bool do_sale(rw_mutex& m) { bool succeeded = false; while (true) { try { return try_sale(m); catch (rw_promotion_error&) { // Try the whole thing again } } }
I believe choice 2 is the only reasonable path. And I also believe that the syntax above might lull a code reader into believing that assert(x==y) should always be true. And therefore I think the following (more explicit) syntax is superior:
void f(read_write_mutex m) { read_write_mutex::read_lock r(m);
int y = x;
if (...) { r.unlock(); read_write_mutex::write_lock w(m);
This is essentially how the w(r) ctor must be implemented, if it is to be implemented at all. One could try a try_lock on w if the read count is 1, and then fall back on the above if that doesn't work, but I'm unsure if that really provides a benefit.
But this doesn't achieve anything - if you release the read lock, then you don't know that what held true while it was read-locked is still true once you have acquired a write lock. If you choose to have lock promotion (having only lock demotion is a viable choice, except that there will be certain usage patterns that are more efficient with a fail-able promotion), then it must at least preserve known state across promotion. Matt.