|
Boost : |
From: Howard Hinnant (hinnant_at_[hidden])
Date: 2004-07-05 21:35:29
On Jul 5, 2004, at 8:27 PM, Matthew Vogt wrote:
> 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:
<snip>
> // Try the whole thing again
Exploring the case: throw exception if unable to atomically promote
read to write:
If an exception is not thrown, then you are guaranteed what you
previously read is still true, and all is well. If an exception is
thrown, then you have to re-read to determine current state.
Hmm...
Given that when you have write privilege you also implicitly have read
privilege, this seems a little extreme. Would it not be both more
efficient and easier to follow if you just reaffirm your state under
the write lock rather than assume your state, and write a catch block
to reassert it if it happens to be false? That is, this:
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)
{
while (true)
{
try_again:
try {
return try_sale(m);
catch (rw_promotion_error&) {
// Try the whole thing again
// how is this implemented?
goto try_again; // ?
}
}
}
vs this:
void do_sale(rw_mutex& m)
{
read_lock rl(m);
long balance = get_balance();
long cost = get_total_cost();
if (balance > cost)
{
rl.unlock(m);
write_lock wl(m);
set_balance(balance - cost);
wl.transfer_to_read_lock(rl);
balance = get_balance();
}
// ...
}
> 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.
My assertion is that you don't know a-priori if the read-to-write
promotion achieves anything or not. If you allow it to fail, by
exception, or by error code, or by any other means, then you have to
write code to re-read the current state. If you don't allow it to
fail, then you must make it block until it succeeds. The latter seems
simpler in logic, and smaller in code size. The logic is quite simple:
read_lock to write_lock promotion is not atomic.
Once that is understood, the programmer can just deal with it. Trying
to encapsulate this bit of reality only serves to obfuscate the
necessary logic.
-Howard
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk