Boost logo

Boost Users :

Subject: Re: [Boost-users] Try-upgrade locking
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2011-12-13 17:37:46


Le 13/12/11 18:57, Kelvin Chung a écrit :
> Suppose I have a boost::upgrade_lock<boost::shared_mutex>. When I
> want to create the boost::upgrade_to_unique_lock<boost::shared_mutex>
> and upgrade to exclusive locking, this blocks until all the shared
> lock holders leave. However, it does not appear that there is a
> non-blocking version of this, unlike, say, making a
> boost::unique_lock<boost::shared_mutex> and passing in
> boost::try_to_lock.
>
> So what should I do in order to create my own "try-upgrade" lock? I'm
> trying to use it like so:
>
> boost::upgrade_lock<boost::shared_mutex> upgradeLock(mutex);
> ...
> if (...) {
> // Substitute for
> boost::upgrade_to_unique_lock<boost::shared_mutex>, but also with
> aspects of
> // boost::try_to_lock, basically
> my_upgrade_to_unique_lock<boost::shared_mutex>
> deferredWriteLock(lock);
>
> // Do stuff where it doesn't matter whether I have exclusive or
> not, while the readers leave
> if (!deferredWriteLock) deferredWriteLock.lock(); // Now we
> need exclusive
> // We have exclusive, do more stuff
> }
> // Back to regular upgrade_lock here
>
>
Hi,

There is a draft proposal from Howard Hinnant "Shared locking in C++"
http://home.roadrunner.com/~hinnant/bloomington/shared_mutex.html that
doesn't have upgrade_to_unique_lock but that allows to try to lock an
upgrade_lock. Even if the interface is a little bit different I guess
that the lecture will help you a lot.

If I understand you wan to lock a mutex with shared ownership until you
need to have exclusive ownership and then retrieve the shard ownership
again. Unfortunately I think that the current interface doesn't let you
to try to move from shared to exclusive ownership without blocking, and
I don't know how to move from a exclusive ownership to a shared on.

If you can block when getting exclusive ownership, you will be able to
implement it with the current interface as follows (Note pseudo-code)

IUC, Howard's proposal contains all the ingredient to do it using a an
initial shared_lock, trying to move to an upgrade_lock and if successful
moving then to a unique_lock and last moving back to the initial
shared_lock. See the example:

upgrade_mutex mut;
// ...
void foo()
{
     shared_lock<upgrade_mutex> sl(mut);
     // mut share locked here
     // ...
     // Try to convert mut from shared to upgrade ownership for 5ms
     // It can succeed if no other thread has upgrade ownership,
     // or is blocked on exclusive ownership.
     upgrade_lock<upgrade_mutex> ul(std::move(sl), chrono::milliseconds(5));
     if (ul.owns_lock())
     {
         // mut upgrade locked here
         // This thread will still share with other threads having shared ownership here.
         // ...
         // Convert mut from upgrade to exclusive, blocking as necessary
         unique_lock<upgrade_mutex> el(std::move(ul));
         // mut exclusive locked here
         // No other threads have shared, upgrade or exclusive ownership here.
         // ...
     }// mut.unlock()
     else
     {
         // mut still share locked here
         // ...
     }
}// if mut is share locked, then mut.unlock_shared()

I plan to adapt it to boost as a replacement of the current
Boost.Thread/Boost.Interprocess implementation, but this will take some
time.

In the mean time you can create some feature requests, I will try to get
them, but I really think the design must be changed globally.

Best,
Vicente



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net