In the following code, it is possible that event throws exception and it may be not handled in even handler, (rare but its still the case)
I want keep "lck2" unlocked while executing the event, because I don't want main thread block for "mtx2", reason is nothing more than optimization.
Can I guarantee that "lck2" is always released in catch block? or there could be runtime exceptions and therefore it may cause deadlocks or some unexpected behavior?
std::unique_lock<std::mutex>lck2(mtx2); // lock used for waiting for event.
while (_isRunning)
{
try
{
while (_isRunning)
{
// cvar2 is condition variable
cvar2.wait(lck2, [&] {return invoke; }); // wait until invoke == true
if (invoke) // if event must be invoked
{
lck2.unlock();
OnEvent(this, someproperty); // may throw exception
lck2.lock();
invoke = false; // execution completed
}
}
}
catch (...) // we need to keep this thread alive at all costs!
{
lck2.lock(); // is this safe?
invoke = false;
}
}
A rewrite of your code would probably be more appropriate, to make it easier for another developer to work on the code. I will show you two rewrites:
First, (Bad)
Second, (Good)
Breaking the (first) code into smaller functional units; we also note that the expression
cvar2.wait(lck2, [&]{ return invoke; })will suspend execution and only return if woken up andinvokeistrue, then we can infer that we only need that expression to wait. Hence we can discard the superfluous use ofinvoke. Hence we have:Where the helpers are defined: