Boost logo

Boost :

Subject: Re: [boost] [thread] On shared_mutex
From: Marsh Ray (marsh_at_[hidden])
Date: 2010-11-29 22:28:29


On 11/29/2010 11:10 AM, Howard Hinnant wrote:
>
> And in the ting version the last line looks like:
>
> lk = unique_lock<upgrade_mutex>(move(ul));
>
> I.e. The type-change must be called out explicitly. Perhaps it is
> just my paranoia, but this library is novel in its ability to change
> the ownership mode of the mutex, and so people may not be expecting
> it.

I had an upgradable lock class going years ago and I found it quite
handy. I'm looking forward to using this next time I need it.

> So I'm trying to make the change of ownership explicit.

Always a good thing.

The facility I used did not use have a different lock type for
'upgradable', all shared locks were upgradeable (of course we called
them read and write locks).

An upgrade operation would always succeed if you were willing to wait
long enough. The way the deadlock issue was handled was simple: it
didn't guarantee that the upgrade would be performed atomically in every
case. Sometimes a different thread would get his exclusive ownership in
between your shared and exclusive locks. Of course, whether or not your
upgrade happened atomically was indicated in the return value.

This allowed a common pattern:

shareable_mutex g_mut;

// Ensure color is made blue, if it isn't already.
// get_color() and set_color() are nontrivial operations.
void ensure_blue()
{
    lock l(g_mut, shared, forever);
    if (get_color() != blue)
    {
        bool upgrade_was_atomic = l.upgrade_to_exclusive(forever);
        if (upgrade_was_atomic || get_color() != blue)
            set_color(blue);
    }
}

So the code didn't need to call get_color() twice when the lock was
upgraded atomically. That was the usual case. I'm sure there's similar
code with your interface.

There were some things I liked about this pattern:
* The code is simple. There's only one lock. The code doesn't have error
conditions to test for, or exceptions being thrown, unless something
else is broken.
* There is one condition that must be checked, but even if you forgot to
check it, it was probably just a missed optimization. You still had an
exclusive lock at that point.
* There was no such thing as a 'lock' object that wasn't actually
locking a mutex.

Interestingly:
* This avoids a context switch over the "upgrade fails, calling code
loops and tries again" methods. The thread asks for an upgrade and he
doesn't resume execution until he has an exclusive.

These days I probably wouldn't block forever on a single lock
acquisition like that. I'm always waiting on at least two objects, one
of them being a global event to signal application shutdown.

- Marsh


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