Я пишу код на C ++ и делаю исчерпывающий поиск по параметрам. Проблема в том, что для каких-то параметров функция может войти в бесконечный цикл, и я не могу ее контролировать (не моя функция, использующая ее как черный ящик). Мой вопрос: могу ли я запустить функцию с «ограничением по времени», чтобы через 10 секунд, например, прервать выполнение функции и перейти к следующей итерации?
for(int i=0; i < 100; i++){
aBlackBoxFunction(i);
/* This function may goes into a infinite loop :(
I want that if it won't end after 10 seconds, the function would abort and move to the next iteration. I can't change the function itself */
}
Вы не можете сделать это безопасно. Реально, вы должны ожидать, что мьютексы выйдут из строя, а память утечет. По этой причине нет стандартной функции C ++.
Обычно каждая ОС предлагает специальные функции для уничтожения потока, но их следует использовать, когда приложение все равно закрывается, и у вас застряли потоки, блокирующие выход из программы. В этих случаях функционирующие потоки все равно отсутствуют, и утечки памяти больше не имеют значения.
Возможное решение на платформе Windows. Используйте на свой страх и риск: P (TerminateThread
все равно небезопасно).
#include <thread>
#include <windows.h>
template <typename Func>
bool time_limited_exec(Func func, DWORD time_limit) {
std::thread thread(func);
bool interrupted = false;
if (WaitForSingleObjectEx(thread.native_handle(), time_limit, TRUE) != WAIT_OEBJECT_0) {
interrupted = true;
TerminateThread(thread.native_handle());
}
thread.join();
return interrupted;
}
Я хотел бы реализовать тривиальный цикл обработки событий и сделать так, чтобы функция «ограниченный по времени» разделяла свою работу на части и периодически проверяла, не было ли событие остановки вызвано в цикле событий после тайм-аута или другого запроса завершения.
Этот подход имеет небольшие накладные расходы, но позволяет прервать работу самым чистым способом.
Вы также можете использовать цикл обработки событий для отправки прогресса, достигнутого функцией, если вы хотите запустить что-то вроде индикатора выполнения, чтобы дать пользователю подсказку во время ожидания.
В качестве альтернативы, вы можете реализовать счетчик для отслеживания бесконечного цикла или рекурсии и просто вернуться после превышения порога. Или таймер и делать работу, пока истекшее время составляет менее 10 секунд.
Недостаток — любые безопасные средства прерывания функции должны быть в нем. Так что вам придется открыть и взломать этот черный ящик.