av4625
av4625

Reputation: 353

What is the difference in boost::shared_mutex vs boost::upgrade_mutex?

I was wondering what the difference is in boost::shared_mutex and boost::upgrade_mutex. I wanted to make a multi threaded application that will have multiple frequent readers and one non frequent writer.

I could just use a standard shared_mutex and a shared_lock and a unique_lock. Although this is likely to give me writer starvation.

What I want is: If a reader has a shared lock and a writer is waiting on the lock that no other readers will be given access and they will have to wait on the shared lock.

I can find very little information on boost::upgrade_mutex, but I think this is what I want?

I made this example (please ignore that the couts are happening outside of a lock etc and that I can't control which thread runs first):

#include <iostream>
#include <thread>

#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>

int main()
{
    boost::shared_mutex mutex;

    boost::shared_lock<boost::shared_mutex> read_lock(mutex);

    std::thread t1([&mutex]()
    {
        std::cout << "Thread trying to get the unique lock!" << std::endl;
        boost::unique_lock<boost::shared_mutex> write_lock(mutex);
        std::cout << "Thread got the unique lock!" << std::endl;
    });

    std::thread t2([&mutex]()
    {
        std::cout << "Thread trying to get the shared lock!" << std::endl;
        boost::shared_lock<boost::shared_mutex> read_lock(mutex);
        std::cout << "Thread got the shared lock!" << std::endl;
    });

    // To make sure the threads ask for the lock before unlocking
    sleep(1);

    std::cout << "Unlocking first lock" << std::endl;
    read_lock.unlock();

    t1.join();
    t2.join();
}

From my testing, if t1 runs before t2, t2 also waits on read_lock.unlock(); before proceeding. This is what I want!

I then changed boost::upgrade_mutex to boost::shared_mutex (in the template param of the locks as well) and I am seeing exactly the same behaviour. I can't find in the documentation if this is guaranteed or what the difference is.

Upvotes: 1

Views: 519

Answers (1)

JVApen
JVApen

Reputation: 11317

Reading the documentation, the upgrade_mutex is a shared_mutex with extra functionality considered upgrading. See https://www.boost.org/doc/libs/1_81_0/doc/html/thread/synchronization.html#thread.synchronization.mutex_concepts.upgrade_lockable

The UpgradeLockable concept is a refinement of the SharedLockable concept that allows for upgradable ownership as well as shared ownership and exclusive ownership. This is an extension to the multiple-reader / single-write model provided by the SharedLockable concept: a single thread may have upgradable ownership at the same time as others have shared ownership. The thread with upgradable ownership may at any time attempt to upgrade that ownership to exclusive ownership. If no other threads have shared ownership, the upgrade is completed immediately, and the thread now has exclusive ownership, which must be relinquished by a call to unlock(), just as if it had been acquired by a call to lock().

The thing you cannot do with shared_lock is upgrading from shared locking to unique locking, without unlocking. The upgrade_lock is something in-between a shared and a unique lock. You can only have a single upgrade lock, though at the same time multiple shared locks can be taken. You can ask to upgrade the upgrade lock to a unique lock, which will only succeed after all shared locks are released. (Other operations are also possible, though they are less relevant to understand the difference)

Upvotes: 1

Related Questions