Skip to content
C++ Basics: Transport Worker Exceptions through a Future

C++ Basics: Transport Worker Exceptions through a Future

November 3, 2026

Catch a worker failure, store it in a promise, and handle it where the future is consumed.

Prepare a scratch directory

Tested on Linux x86_64 with GCC 14.2.0. Install a C++20-capable GCC compiler and its standard-library development files, with g++ on PATH. You also need Bash, a text editor, and mktemp, rm, and rmdir. No third-party library is required.

Keep the same terminal open. Stop if setup fails before saving the source:

start_directory="$PWD"
work_directory="$(mktemp -d)" || exit 1
cd -- "$work_directory" || exit 1

Run the example

Save this as promise-future-exception-demo.cpp:

#include <exception>
#include <future>
#include <iostream>
#include <stdexcept>
#include <thread>

int main()
{
    std::promise<int> result_promise;
    auto result_future = result_promise.get_future();
    std::jthread worker([&] {
        try {
            throw std::runtime_error("invalid job input");
        } catch (...) {
            result_promise.set_exception(std::current_exception());
        }
    });
    try {
        const int result = result_future.get();
        std::cout << "Result: " << result << '\n';
    } catch (const std::runtime_error& error) {
        std::cout << "Worker failed: " << error.what() << '\n';
    }
    worker.join();
}

Compile and run it. The second command runs only after compilation succeeds:

g++ -std=c++20 -Wall -Wextra -Werror -pedantic -pthread promise-future-exception-demo.cpp -o promise-future-exception-demo &&
./promise-future-exception-demo

Observed output:

Worker failed: invalid job input

Read the result

The exception does not escape the thread entry function. current_exception captures the active exception, and set_exception makes the shared state ready. The future get waits if necessary and rethrows that exception in main, where it is caught and printed.

Apply it carefully

An exception escaping a thread entry function terminates the program; it is not automatically forwarded to the joining thread. Fulfill a promise exactly once with either a value or an exception. In this example only one worker owns that responsibility. A regular future consumes its result on get, so do not call get twice.

The C++ working draft documents the relevant rules. This example uses C++20 facilities; the current draft also contains newer additions.

Clean up

Remove only the source and executable created here, then remove the empty practice directory:

rm -- promise-future-exception-demo.cpp promise-future-exception-demo
cd -- "$start_directory" || exit 1
rmdir -- "$work_directory"
unset start_directory work_directory

If the directory is not empty, inspect its remaining contents before removing anything else.

Acknowledgements

This post was created with assistance from AI.

Last updated on