$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Matthew Vogt (mvogt_at_[hidden])
Date: 2004-07-05 19:27:53
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.