Как зарегистрировать обработчик выхода потока в C ?

#c #multithreading #synchronization

#c #многопоточность #синхронизация

Вопрос:

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

Это выглядит примерно так:

 boost::promise<bool> promiseThreadStart;

void threadEntry();

int main(int argc, char* argv[])
{
    // Prepare promise/future
    promiseThreadStart = boost::promise<bool>();
    boost::unique_future<bool> futureThreadStarted = promiseThreadStart.get_future();

    // Start thread
    boost::thread threadInstance = boost::thread(threadEntry);

    // Wait for the thread to successfully initialize or to fail
    try {
        bool threadStarted = futureThreadStarted.get();
        // Started successfully
    }
    catch (std::exception amp;e) {
        // Starting the thread failed
    }

    return 0;
}

void threadEntry() {
    // Do some preparations that could possibly fail
    if (initializationFailed) {
        promiseThreadStart.set_exception(std::runtime_error("Could not start thread."));
        return;
    }

    // Thread initialized successfully
    promiseThreadStart.set_value(true);

    // Do the actual work of the thread
}
  

Что меня здесь расстраивает, так это тот факт, что поток может завершиться сбоем на этапе инициализации с ошибкой, которую я не обрабатываю. Тогда я бы не стал устанавливать правильное исключение для обещания, и основная функция будет бесконечно ждать future.get() возврата. Имея это в виду, мое решение кажется мне довольно подверженным ошибкам и плохо разработанным.

Я узнал о RAII и о том, как он обеспечивает безопасность исключений, потому что вы можете выполнить очистку в деструкторе. Я хотел бы применить аналогичный шаблон к ситуации, упомянутой выше. Поэтому мне интересно, есть ли что-то вроде деструктора потока или обработчика выхода, где я мог бы установить исключение по умолчанию для обещания. Но в любом случае, использование этого обещания / будущего дизайна кажется мне грязным обходным путем. Итак, каков наилучший и самый элегантный способ добиться безопасного ожидания без исключений?

Комментарии:

1. Может быть, передать a std::function в вашу потоковую функцию?

2. set_value_at_thread_exit и set_exception_at_thread_exit .

3. Кроме того, вы могли бы использовать a std::condition_variable с оболочкой RAII, которая освобождается при выходе из потока (или вручную освобождается, как только ваш поток «запущен»)

4. Я предполагаю, что если я использую set_exception_at_thread_exit , будет установлено общее состояние обещания, поэтому я больше не смогу использовать set_value . И написание RAII-оболочки означает: нет готового к использованию потокобезопасного решения, и я должен реализовать его сам?

Ответ №1:

Наконец, я случайно нашел ответ: я думаю, это можно сделать с std::condition_variable помощью времени, в течение которого ожидающие потоки могут быть уведомлены, std::notify_all_at_thread_exit если вновь созданный поток завершается преждевременно.

Комментарии:

1. Следите за cplusplus.github.io/LWG/issue3343