$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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