Recently, Scott Meyers, the author of “Effective Modern C++” book gave a webinar presentation titled Consider void Futures for One‑Shot Event Communication, which addressed the issue of how to enable two threads to communicate to each other when a particular task A was completed, but which do not require any shared state.
The solution is to use a RAII (Resource Allocation Is Initialization, Item 37 in the book):
class ThreadRAII { public: enum class DtorAction { join, detach }; ThreadRAII(std::thread&& t, DtorAction a) : action(a), t(std::move(t)) {} ~ThreadRAII() { if (t.joinable()) { if (action == DtorAction::join) t.join(); else t.detach(); } } ThreadRAII(ThreadRAII&&) = default; // support ThreadRAII& operator=(ThreadRAII&&) = default; // moving std::thread& get() { return t; } private: DtorAction action; std::thread t; };
and then use it when launching the threads:
{ std::promise<void> p; // created first, std::thread t2([&p] // destroyed last { try { p.get_future().get(); funcToRun(); } catch(...) { ... } }); ThreadRAII tr(std::move(t2), // created after ThreadRAII::DtorAction::join); // p, destroyed ... // before p p.set_value(); ... } // if p hasn’t been set, tr’s // d`tor hangs on a join
There are a few nuances, please see the full deck of slides for the full information.
Leave a Reply