← Назад ко всем вопросам

Как сообщить другому потоку про брошенный exception

1️⃣ Как кратко ответить

Для передачи исключения между потоками в C++ можно использовать std::promise и std::future. Поток, в котором возникает исключение, устанавливает его в std::promise, а другой поток получает его через связанный std::future и обрабатывает.

2️⃣ Подробное объяснение темы

В многопоточных приложениях на C++ часто возникает необходимость передавать информацию об исключениях между потоками. Это важно для корректной обработки ошибок и предотвращения некорректного завершения программы. Для этого в C++ можно использовать механизмы std::promise и std::future.

Зачем это нужно

Когда в одном потоке возникает исключение, оно не может быть автоматически передано в другой поток. Если не обработать исключение, это может привести к завершению потока и, возможно, всей программы. Поэтому важно иметь механизм для передачи информации об исключении в другой поток, который может его обработать.

Как это работает

std::promise и std::future — это стандартные инструменты C++ для асинхронного программирования. std::promise позволяет установить значение или исключение, которое будет доступно через связанный std::future. std::future предоставляет интерфейс для получения этого значения или исключения.

Пример кода

#include <iostream>
#include <thread>
#include <future>
#include <stdexcept>
​
// Функция, выполняемая в отдельном потоке
void threadFunction(std::promise<int>& prom) {
    try {
        // Имитация работы, которая может вызвать исключение
        throw std::runtime_error("Exception in thread");
    } catch (...) {
        // Устанавливаем исключение в promise
        prom.set_exception(std::current_exception());
    }
}
​
int main() {
    // Создаем promise и получаем связанный с ним future
    std::promise<int> prom;
    std::future<int> fut = prom.get_future();
​
    // Запускаем поток, передавая в него promise
    std::thread t(threadFunction, std::ref(prom));
​
    try {
        // Ожидаем результат из future
        int result = fut.get();
    } catch (const std::exception& e) {
        // Обрабатываем исключение, переданное из потока
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
​
    // Ожидаем завершения потока
    t.join();
​
    return 0;
}

Пояснение кода

  1. Создание std::promise и std::future:

    • std::promise<int> prom; — создается объект std::promise, который будет использоваться для передачи исключения.
    • std::future<int> fut = prom.get_future(); — создается std::future, связанный с std::promise, который будет использоваться для получения результата или исключения.
  2. Запуск потока:

    • std::thread t(threadFunction, std::ref(prom)); — запускается новый поток, которому передается ссылка на std::promise.
  3. Обработка исключения в потоке:

    • Внутри threadFunction происходит попытка выполнения кода, который может вызвать исключение.
    • Если исключение возникает, оно перехватывается и устанавливается в std::promise с помощью prom.set_exception(std::current_exception());.
  4. Получение и обработка исключения в основном потоке:

    • int result = fut.get(); — основной поток ожидает результат из std::future. Если в std::promise было установлено исключение, оно будет выброшено здесь.
    • Исключение перехватывается и обрабатывается в блоке catch, выводя сообщение об ошибке.
  5. Завершение потока:

    • t.join(); — основной поток ожидает завершения работы потока, чтобы корректно завершить программу.

Использование std::promise и std::future позволяет безопасно и эффективно передавать исключения между потоками, обеспечивая надежную обработку ошибок в многопоточных приложениях.

Тема: Исключения / noexcept / Safety
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки