Вопрос

I have a numbers of objects, each associated with a boost::shared_mutex (I need the shared/unique lock capability).

In some occasion in the code I need to obtain unique ownership of multiple objects at once.

for (FileMetaData* entry : smd->fileSet) {
    entry->fileMutex.lock();
}

// some critical work

for (FileMetaData* entry : smd->fileSet) {
    entry->fileMutex.unlock();
}

Doing something like this results in deadlock when different threads try to obtain different sets of locks.

I found that std::lock () suits my use-case. But is there an equivalence for boost::shared_mutex?

Edit:

Regarding the ordered locking pattern, it doesn't work exactly for my case:

T1 lock (C,D,E)
T2 wants to lock (B,D), but can only obtain the lock for B
T1 spawns T3 which works on (B,C), it stuck when obtaining the lock for B

So the problem is that an extra lock on B is required when T1 spawns T3, this breaks the ordered locking pattern. I think this problem can be solved if T2 doesn't hold the lock for B when D is not lockable, essentially what std::lock does.

Это было полезно?

Решение

You can use std::lock (or equivalently boost::lock, collectively "the lock functions") to perform shared ownership locking as well as exclusive locking, depending on what you pass in to be locked - anything Lockable will work. For example, if you have want to lock two std::mutex/boost::mutexs A, B and boost::shared_mutex SM in exclusive mode, you simply pass the three to std::lock:

std::lock(A, B, SM);

if you instead want to lock SM in shared ownership mode, you can create an unlocked boost::shared_lock for it and pass that into the locking functions:

boost::shared_lock<boost::shared_mutex> bsl{SM, boost::defer_lock};
std::lock(A, B, bsl);

On a note unrelated to your question - style preference - I prefer to always construct RAII locks to pass into std::lock so I can't screw up unlocking, so I'd actually write:

auto alk = boost::make_unique_lock(A, std::defer_lock);
auto blk = boost::make_unique_lock(B, std::defer_lock);
// boost::make_shared_lock(), where are you?!?
boost::shared_lock<boost::shared_mutex> bsl{SM, boost::defer_lock};
std::lock(alk, blk, bsl);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top