HPX - High Performance ParalleX

PrevUpHomeNext

Working with Exceptions

Like in any other asynchronous invocation scheme it is important to be able to handle error conditions occurring while the asynchronous (and possibly remote) operation is executed. In HPX all error handling is based on standard C++ exception handling. Any exception thrown during the execution of an asynchronous operation will be transferred back to the original invocation locality, where it is rethrown during synchronization with the calling thread.

The source code for this example can be found here: error_handling.cpp.

For the following description we assume that the function raise_exception() is executed by invoking the plain action raise_exception_type:

void raise_exception()
{
    HPX_THROW_EXCEPTION(hpx::no_success, "raise_exception", "simulated error");
}
HPX_PLAIN_ACTION(raise_exception, raise_exception_type);

The exception is thrown using the macro HPX_THROW_EXCEPTION. The type of the thrown exception is hpx::exception. This allows to associate additional diagnostic information with the exception, such as file name and line number, locality id and thread id, and stack backtrace from the point where the exception was thrown.

Any exception thrown during the execution of an action is transferred back to the (asynchronous) invocation site. It will be rethrown in this context when the calling thread tries to wait for the result of the action by invoking either future<>::get() or the synchronous action invocation wrapper as shown here:

try {
    // invoke raise_exception() which throws an exception
    raise_exception_type do_it;
    do_it(hpx::find_here());
}
catch (hpx::exception const& e) {
    // Print just the essential error information.
    hpx::cout << "caught exception: " << e.what() << "\n\n";

    // Print all of the available diagnostic information as stored with
    // the exception.
    hpx::cout << "diagnostic information:"
        << hpx::diagnostic_information(e) << "\n";
}
[Note] Note

The exception is transferred back to the invocation site even if it is executed on a different locality.

Additionally, this example demonstrates how an exception thrown by an (possibly remote) action can be handled. It shows the use of hpx::diagnostic_information() which retrieves all available diagnostic information from the exception as a formatted string. This includes, for instance, the name of the source file and line number, the sequence number of the OS-thread and the HPX-thread id, the locality id and the stack backtrace of the point where the original exception was thrown.

Under certain circumstances it is desireable to output only some of the diagnostics, or to output those using different formatting. For this case, HPX exposes a set of lower level functions as demonstrated in the following code snippet:

try {
    // invoke raise_exception() which throws an exception
    raise_exception_type do_it;
    do_it(hpx::find_here());
}
catch (hpx::exception const& e) {
    // Print the elements of the diagnostic information separately
    hpx::cout << "[locality-id]: " << hpx::get_locality_id(e) << "\n";
    hpx::cout << "[hostname]: "    << hpx::get_host_name(e) << "\n";
    hpx::cout << "[pid]: "         << hpx::get_process_id(e) << "\n";
    hpx::cout << "[function]: "    << hpx::get_function_name(e) << "\n";
    hpx::cout << "[file]: "        << hpx::get_file_name(e) << "\n";
    hpx::cout << "[line]: "        << hpx::get_line_number(e) << "\n";
    hpx::cout << "[os-thread]: "   << hpx::get_os_thread(e) << "\n";
    hpx::cout << "[thread-id]: "   << std::hex << hpx::get_thread_id(e) << "\n";
    hpx::cout << "[thread-description]: "
        << hpx::get_thread_description(e) << "\n\n";

    hpx::cout << hpx::flush;
}

Please refer to the documentation of hpx::get_locality_id(), hpx::get_host_name(), hpx::get_process_id(), hpx::get_function_name(), hpx::get_file_name(), hpx::get_line_number(), hpx::get_os_thread(), hpx::get_thread_id(), and hpx::get_thread_description() for more details.


PrevUpHomeNext