Reputation: 4975
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.
Upvotes: 2
Views: 1142
Reputation: 42554
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::mutex
s 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);
Upvotes: 1