#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