|
Boost : |
From: Howard Hinnant (hinnant_at_[hidden])
Date: 2004-07-22 16:36:41
On Jul 22, 2004, at 2:37 PM, Eric Niebler wrote:
> The scoped_lock assignment operators make me a bit nervous. For
> instance, you don't specify what this should do:
>
> Mutex mut;
> scoped_lock< Mutex > l1( mut ); // lock once
> scoped_lock< Mutex > l2( mut ); // lock twice (recursive)
> l1 = move(l2); // ???
>
> If I had to guess, I suppose this would have the effect of simply
> unlocking l2. Or should it throw? I would prefer the former if I had
> to choose, but the specification should be clear on this point.
Excellent point. I did not consider the possibility of a recursive
mutex when I wrote the spec for this, nor when I prototyped it. You've
found a bug in both the spec and my prototype.
The (proposed) move assignment philosophy is:
l1 = move(l2);
behaves as if:
atomic
{
if (l1.locked())
l1.unlock();
if (l2.locked())
{
l2.unlock();
l1.lock();
}
}
So in your example l2 would be unlocked, l1 would remain locked, and
the underlying mutex lock count would be decremented by 1.
Proposed spec:
Effects: Throws a lock_error() if mutex() != sl.p_->mutex(). If
locked() before the call, then unlock() is called on the mutex.
Postconditions: locked() == the value of sl.p_->locked() before the
assignment. sl.p_->locked() == false after the assignment.
Notes: This scoped_lock relinquishes any mutex ownership it has. Then
if the sl scoped_lock owns the mutex, ownerhisp is transferred to this
scoped_lock with no blocking. If the sl scoped_lock does not own the
mutex, then neither will this scoped_lock after the assignment. Only
rvalue scoped_lock's will match this signature. lvalue scoped_lock's
can not transfer ownership unless "cast" to an rvalue. An lvalue
scoped_lock can be "cast" to an rvalue with the expression: move(lock);
Thanks for the catch.
-Howard
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk