Middle+
How to check if an exception occurred in one of the threads?
sobes.tech AI
Answer from AI
There are several ways:
- Future and std::async:
std::asyncreturns astd::future. When trying to get the result from the future (for example, usingfuture.get()) in the main thread, if an exception occurred in the asynchronous task, it will be re-thrown in the main thread. - std::promise and std::future: A thread where an exception might occur can "capture" the exception and store it in a
std::promiseusingpromise.set_exception(). Another thread can obtain (promise.get_future()) the correspondingstd::futureand, upon callingfuture.get(), receive the stored exception. - try-catch inside the thread and status passing: Wrap potentially "dangerous" code inside a
try-catchblock within the thread. In case of an exception, store a pointer to it (usingstd::current_exception()) or a special flag in a shared variable, with access synchronized. boost::exceptionlibrary:boost::exceptionprovides more powerful mechanisms for capturing, storing, and passing exceptions between threads, allowing attaching additional information to the exception.
Example with std::async:
#include <iostream>
#include <future>
#include <thread>
#include <vector>
#include <exception>
// Function that may throw an exception
int divide(int a, int b) {
if (b == 0) {
throw std::runtime_error("Division by zero!");
}
return a / b;
}
int main() {
// Launch an asynchronous task
std::future<int> fut = std::async(std::launch::async, divide, 10, 0);
try {
// Attempt to get the result. If an exception occurred, it will be thrown here.
int result = fut.get();
std::cout << "Result: " << result << std::endl;
} catch (const std::exception& e) {
// Handle the exception that occurred in the other thread
std::cerr << "Caught exception from thread: " << e.what() << std::endl;
}
return 0;
}
Example with std::promise and std::future:
#include <iostream>
#include <future>
#include <thread>
#include <exception>
void worker_function(std::promise<int>&& prom) {
try {
// Code that may throw an exception
int result = 5 / 0; // Suppose an error occurs here
prom.set_value(result); // Set successful value
} catch (...) {
// Capture the current exception
try {
prom.set_exception(std::current_exception()); // Set the exception
} catch (...) {
// An error occurred while setting the exception (unlikely)
}
}
}
int main() {
std::promise<int> prom;
std::future<int> fut = prom.get_future();
// Launch a thread with worker_function
std::thread t(worker_function, std::move(prom));
try {
// Try to get the result from future
int result = fut.get();
std::cout << "Result: " << result << std::endl;
} catch (const std::exception& e) {
// Handle the exception that was set in the promise
std::cerr << "Caught exception from thread: " << e.what() << std::endl;
}
t.join(); // Wait for the thread to finish
return 0;
}
The choice of method depends on the application's architecture and error handling requirements. std::async and std::future are the simplest way to pass results and exceptions from one-off tasks. std::promise and std::future offer more flexibility. Manual status or exception storage is suitable for specific scenarios with custom synchronization logic.