c++ - Is this code exceptions handled correctly? -


in following code, possible event throws exception , may not handled in handler, (rare still case)

i want keep "lck2" unlocked while executing event, because don't want main thread block "mtx2", reason nothing more optimization.

can guarantee "lck2" released in catch block? or there runtime exceptions , therefore may cause deadlocks or unexpected behavior?

std::unique_lock<std::mutex>lck2(mtx2); // lock used waiting event.  while (_isrunning)  {     try     {         while (_isrunning)         {             // cvar2 condition variable             cvar2.wait(lck2, [&] {return invoke; }); // wait until invoke == true              if (invoke) // if event must invoked             {                 lck2.unlock();                 onevent(this, someproperty); // may throw exception                 lck2.lock();                  invoke = false; // execution completed             }         }     }     catch (...) // need keep thread alive @ costs!     {                     lck2.lock(); // safe?         invoke = false;     } } 

a rewrite of code more appropriate, make easier developer work on code. show 2 rewrites:

  • first, (bad)

    while (true) {     try     {         {              std::lock_guard<std::mutex> lckx(mtx2);              if(!_isrunning)                    break;    //out of main loop         }          bool should_invoke = false;         {                 std::unique_lock<std::mutex> lck2(mtx2);                 cvar2.wait(lck2, [&] {return invoke; });                 should_invoke = invoke;         }               if (should_invoke) // if event must invoked         {             onevent(this, someproperty); // may throw exception             {                 std::lock_guard<std:mutex> lckx(mtx2);                 invoke = false; // execution completed             }         }     }     catch (...) // need keep thread alive @ costs!     {                     std::lock_guard<std:mutex> lckx(mtx2);         invoke = false;     } } 

  • second, (good)

    breaking (first) code smaller functional units; note expression cvar2.wait(lck2, [&]{ return invoke; }) suspend execution , return if woken and invoke true, can infer need expression wait. hence can discard superfluous use of invoke. hence have:

    void do_work(){     while(is_running()){         try{              wait_for_invocation();              onevent(this, someproperty); // may throw exception              set_invocation_state(false);         catch(...){              set_invocation_state(false);         }     } } 

    where helpers defined:

    bool is_running(){     std::lock_guard<std::mutex> lckx(mtx2);     return _isrunning; }  void wait_for_invocation(){     std::unique_lock<std::mutex> lck2(mtx2);     cvar2.wait(lck2, [&] {return invoke; }); }  void set_invocation_state(bool state){     std::lock_guard<std::mutex> lckx(mtx2);     invoke = state; } 

Comments

Popular posts from this blog

python - Selenium remoteWebDriver (& SauceLabs) Firefox moseMoveTo action exception -

html - How to custom Bootstrap grid height? -

angular - Copying node modules to wwwroot AspNetCore -