I have a class that protects a resource from concurrent access like -
class Protector{ Resource R; shared_mutex _m;
... some 5-6 methods that access resource R like
void safeResourceOperation(){
lock_guard lock(_m);
// do Operation on R
}
}
Now for a specific usecase, there's a need to share this mutex with outside world. Instead of making this mutex public and risk leaving it locked by someone, I provided a method that takes lambda and calls it under lock guard, for eg. -
class Protector{
template<typename Fn> void lockedOp(Fn f) {
lock_guard lock(_m);
f();
}
}
Now the problem arises when some user of this class tries to do this -
Protector p;
p.lockedOp([&]{
// does something and then
p.safeResourceOperation() // <-- results in deadlock
});
To solve this, I thought of keeping a boolean variable inside lockedOp that disables mutex on all safeFunctions while it's being called -
template<typename Fn> void lockedOp(Fn f) {
lock_guard lock(_m);
atomic_bypass_mutex = true;
f();
atomic_bypass_mutex = false;
}
void safeResourceOperation(){
if(!atomic_bypass_mutex) {
lock_guard lock(_m);
doOperationsOnResource();
} else {
doOperationsOnResource();
}
}
But there would be a problem when lockedOp
is being called in thread1
and sets bypass = True
and some other thread2
calls p.safeResourceOperation()
(not inside lockedOp
). It will also get bypassed mutex and thread-safety gets compromised.
How should I solve this problem? One alternative that I see is keeping thread-id's and their thread-local
boolean variables in a map and only allowing bypasses for the same thread-id. But I've a feeling this might be a bit complex solution.
Personally I find your usage of protector a bit strange. Your are mixing concepts by putting business logic inside of your protector, specifically the safeResourceOperation method.
Protector p;
p.lockedOp([&]{
// does something and then
p.safeResourceOperation(); // <-- results in deadlock
});
I would expect a better design would be to extract the protector logic, so you'll get something like:
Protector<Resource> p;
p.lockedOp([&](auto &resource){
// does something and then
resource.safeResourceOperation();
});
If you really care about non-locked access this class can also provide an extra method.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.