Boost logo

Boost :

From: Michael Glassford (glassfordm_at_[hidden])
Date: 2004-06-29 13:45:34


Peter Dimov wrote:
> Michael Glassford wrote:
>
>>Also, you could end up with some interesting situations like this:
>>
>> void f(read_write_mutex m)
>> {
>> read_write_mutex::read_lock r(m);
>> if (...)
>> {
>> read_write_mutex::write_lock w(r); //lock promotion
>> //...
>> }
>> //Point A
>> }
>>
>>The most obvious implementation of promotion would be for the write lock
>>to unlock the read lock if promotion succeeded, but leave it locked if
>>promotion failed. But in the above code, this would mean that if
>>promotion succeeds, neither lock will be locked at "Point A"; however
>>if promotion fails, r will still be read-locked at point A.
>
>
> Not necessarily, ~write_lock can (should) demote the lock back to read (or
> whatever the initial condition of r was).

True. But then, in the reverse case:

      void f(read_write_mutex m)
      {
          read_write_mutex::write_lock w(m);
          if (...)
          {
              read_write_mutex::read_lock r(w); //lock demotion
              //...
          }
          //Point A
      }

It may not be possible for r's destructor to re-obtain the write lock,
which means that, at point A:

1) If the write lock can be re-obtained, w is write-locked.

2) Otherwise, w is either unlocked or read-locked. The idea of a
write-lock being read-locked is pretty strange, but having it unlocked
doesn't seem a good choice, either.

I realize that a combined read-write lock has the same problem of
possibly being unable to re-obtain the write-lock, but in that case it
is at least more obvious that the lock state changed and what it changed to:

      void f(read_write_mutex m)
      {
          read_write_mutex::read_write_lock l(m, write_locked);
          if (...)
          {
              l.demote(); //lock demotion
              //...
          }
          //Point A: l is read-locked
      }

Or:

      void f(read_write_mutex m)
      {
          read_write_mutex::read_write_lock l(m, write_locked);
          if (...)
          {
              l.demote(); //lock demotion
              //...
              l.try_promote(); //optional
          }
          //Point A: l is write-locked if try_promote() succeeded,
          //read-locked if it failed; never unlocked.
      }

Finally, to take two more realistic use cases:

      void f(read_write_mutex m)
      {
          read_write_mutex::write_lock w(m);

          //...

          read_write_mutex::read_lock r(w); //lock promotion

         //...
      }

And:

      void f(read_write_mutex m)
      {
          read_write_mutex::write_lock r(m);

          //...

          read_write_mutex::read_lock w(r); //lock demotion

         //...
      }

The second lock does unnecessary work in demoting/promoting the lock for
the first lock, which then immediately unlocks it.

Don't get me wrong: I actually like the idea of separate read and write
locks, but there seem to be some tricky problems to address to make them
work with lock promotion/demotion.

Mike


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk