It is a common practice to use guards, RAII and try/catch blocks to ensure that a thread will be eventually joined in all cases. However, what about threads that are meant to be detached?
void aFunction() {
std::thread t {someOtherFunction}; // someOtherFunction may throw!!!
t.detach;
}
Am I supposed to use some exception handling mechanism to make sure that t will be properly detached even in the case of an exception or does it not really matter?
std::thread t {someOtherFunction}; // someOtherFunction may throw!!
If someOtherFunction can throw, then the exception needs to be handled in that function. If not, the default behaviour is to call std::terminate if the exception "escapes" the thread function.
The std::thread object construction and std::thread::detach itself can also throw, so these exceptions need to be handled by the aFunction().
The detach() method throws if thread object is not joinable. So if you wish to avoid handling this exception, you can add a test to see if the thread is joinable before attempting to detach it.
if (t.joinable())
t.detach;
The fact that you are called detach() indicates that you do not wish to "join" (synchronise with) the thread at a later stage and it will basically take care of itself.
As with most exception handling questions, what are you going to do with the exception that is thrown? If the exception cannot be handled, then either don't catch it or catch it, log it and rethrow it (or call std::terminate).
The fact that ~thread calls std::terminate if not joined is considered a flaw in the standard.
Scott Meyers recommends using ThreadRAII wrapper that joins the thread in the destructor if it is still joinable:
class ThreadRAII {
public:
ThreadRAII(std::thread&& thread): t(std::move(thread)) {}
~ThreadRAII() { if (t.joinable()) (t.join(); }
private:
std::thread t;
};
If someOtherFunction throws an exception in another thread and no one catches that exception, std::terminate is called.
Use std::current_exception and std::rethrow_exception to catch the exception, transport it to another thread and re-throw it. E.g.:
void thread_function(std::exception_ptr* exception)
try {
throw std::runtime_error("test exception");
}
catch(std::exception& e) {
*exception = std::current_exception();
}
int main() {
// Thread creation.
std::exception_ptr other_thread_exception;
std::thread t{thread_function, &other_thread_exception};
// Thread termination.
t.join();
if(other_thread_exception)
std::rethrow_exception(other_thread_exception);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With