Boost logo

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