Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2004-08-04 20:06:43


On Aug 4, 2004, at 4:45 PM, Bronek Kozicki wrote:

> Is there any reason for distinction between shared lock and upgradable
> shared lock? I mean - obviously updgradable shared lock can be
> upgraded to exclusive one, but do we need separate type for this?
> What's rationale behind this distinciton? I can easily imagine design
> (and implementation) where every shared lock is also upgradable one,
> if it's mutex type support upgrade operation. Under such design one
> can upgrade shared lock only if it's the only (currently locking) lock
> on synchromization object (supporting such transition). Implementation
> of such mutex could be very similar to semaphore (or just using
> semaphore, if present on platform).

The advantage of the separate upgradable_lock type is that when an
upgradable_lock transfers ownership to a scoped_lock, then the thread
can assume that what was read while holding upgradable ownership is
still valid (does not need to be re-read, re-computed) while holding
the scoped_lock. This is true even if the thread had to block while
transferring mutex ownership from the upgradable_lock to the
scoped_lock.

If sharable_lock can transfer mutex ownership to scoped_lock, then the
thread can no longer make this assumption. If the thread blocks for
this ownership transfer, it is possible that another thread will
interrupt, upgrade a sharable_lock, and write. The original thread,
upon obtaining the scoped_lock, is forced to re-read or re-compute its
data upon obtaining the scoped_lock ownership because of this
possibility. Thus it might as well just have relinquished shared
ownership and blocked for exclusive ownership.

Having said that, it is true that we could add:

bool try_unlock_sharable_and_lock();

to the mutex functionality.

This would mean adding the following to scoped_lock:

     scoped_lock(rvalue_ref<sharable_lock<mutex_type> > r,
detail::try_lock_type);
     scoped_lock& operator<<=(rvalue_ref< sharable_lock<mutex_type> > r);

Meaning, you could try to upgrade a sharable_lock to a scoped_lock, but
there would be no way to force the upgrade. It adds an unsymmetric
aspect to the interface: every other try-function has a corresponding
blocking function.

Aside from the asymmetry, I also wonder about the practicality of such
an operation. A shared_lock context is usually set up because one
anticipates common simultaneous non-destructive locking. If
simultaneous non-destructive locking is rare, there is no advantage
over exclusive locking. So if simultaneous non-destructive locking is
common, that means a successful call to try_unlock_sharable_and_lock()
will be rare (and if it isn't, then a simple exclusive mutex would have
probably been a better design). It occurs to me that offering such an
interface might be encouraging an interface that blocks a thread
indefinitely (just keeps trying). Whereas if the code had just
relinquished shared ownership and blocked for exclusive, then the mutex
design is likely to already be set up to not starve writers.

-Howard


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