Home C++ Decisions Loops Input/Output Functions Stack and Heap References Arrays Searching and Sorting Recursion Pointers Character and Strings Structures Classes Inheritance Exceptions Templatess STL Modern C++ Misc Books ----

Threads


Contents

Exceptions

If a thread throws an exception then it will not be caught in the main. Either the thread should catch the exception or else we need some other way to let the main catch the exception.

File: except_main_catch.cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>


using namespace std ;
mutex mutexObj1 ;
mutex mutexObj2 ;





void function1()
{
    throw 1 ;

}



int main()
{
   try
   {
     thread th1 ( function1 ) ;

     th1.join() ;
   }
   catch( int& x1 )

   cout << "Main:" << endl ;

  return 0 ;
}
$ g++ except_main_catch.cpp ; ./a.exe
terminate called after throwing an instance of 'int'
Aborted

The above file shows that even if we place a try catch in the main it does not catch the exception thrown by a thread.

File: except_async1.cpp
#include <iostream>
#include <future>
#include <stdexcept>
#include <thread>

using namespace std ;

// Function that runs in the worker thread and throws an exception
void throw_exception_function()
{
    cout << "Worker thread ID: " << this_thread::get_id() << endl;
    // Simulate some work
    throw runtime_error("Something went wrong in the worker thread!");
}

int main()
{
    try
    {
        // Use async to run the function asynchronously.
        // It returns a future object.
        future<void> future_result = async(launch::async, throw_exception_function);

        cout << "Main thread ID: " << this_thread::get_id() << endl;
        cout << "Waiting for the worker thread to finish..." << endl;

        // Call .get() on the future. If the function threw an exception,
        // .get() will re-throw that exact exception in the main thread.
        future_result.get();

    }
    catch (const runtime_error& e)
    {
        cerr << "Caught exception in main: " << e.what() << endl;
    }
    catch (...)
    {
        cerr << "Caught an unknown exception in main." << endl;
    }

    return 0;
}

$ g++ except_async1.cpp ; ./a.exe
Main thread ID: Worker thread ID: 0xa000165b00xa00000010

Waiting for the worker thread to finish...
Caught exception in main: Something went wrong in the worker thread!


File: except_promise.cpp
#include <iostream>
#include <thread>
#include <future>
#include <stdexcept>
#include <string>

using namespace std ;

void worker_with_promise(promise<void>&& promise_obj)
{
    try
    {
        // Simulate work and an error
        throw runtime_error("Error occurred in manual thread management.");
        // If no exception, you could fulfill the promise like this:
        // promise_obj.set_value();
    }
    catch (...)
    {
        // Catch the exception within the worker thread and store it in the promise
        promise_obj.set_exception(current_exception());
    }
}

int main()
{
    promise<void> promise_obj;
    future<void> future_obj = promise_obj.get_future();
    thread th(worker_with_promise, move(promise_obj));

    try
    {
        // Wait for the result/exception
        future_obj.get();
        cout << "Thread finished successfully (should not happen in this example)." << endl;
    }
    catch (const runtime_error& e)
    {
        cerr << "Caught exception in main: " << e.what() << endl;
    }

    th.join(); // Clean up the thread
    return 0;
}

$ g++ except_promise.cpp ; ./a.exe
Caught exception in main: Error occurred in manual thread management.

We can also use "exception_ptr" .

File: except_global.cpp
#include <iostream>
#include <thread>
#include <exception>
#include <stdexcept>
#include <mutex>

using namespace std ;

exception_ptr global_eptr = nullptr;
mutex eptr_mutex;




void worker_function()
{
    try
    {
        throw runtime_error("Something went wrong in the worker!");
    }
    catch (...)
    {
        lock_guard<mutex> lock(eptr_mutex);
        global_eptr = current_exception(); // Capture the exception
    }
}

int main()
{
    thread worker(worker_function);
    worker.join(); // Wait for the worker to finish

    // Check if an exception was captured
    if (global_eptr)
    {
        try
        {
            //Throws the previous exception in exception_ptr
            rethrow_exception(global_eptr); // Rethrow the captured exception
        }
        catch (const exception& e1)
        {
            cerr << "Caught exception in main thread: " << e1.what() << endl;
        }
    }

    return 0;
}

Exercise

1) Solve the exception issue in the following code by using each approach mentioned in the above section.

File: except_ex1.cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>


using namespace std ;

int divide(  int dividend, int divisor )
{
    if (  divisor == 0 )
      throw string( "Divisor is 0." ) ;
    return dividend/divisor ;

}



int main()
{
   try
   {
     thread th1 ( divide, 5, 0 ) ;

     th1.join() ;
   }
   catch( string& messg )
   {
       cout << "Catch handler in main: " << messg << endl ;
   }
   cout << "Main:" << endl ;

  return 0 ;
}
















































Solutions

1)

File: atomic2.cpp