Прежде всего доступ к isRunning
должен быть синхронизирован. В вашем примере вы можете просто использовать std::atomic<bool>
и покончить с этим.
Отказ от ответственности: прошло много времени с тех пор, как я выполнил какую-либо серию многопоточности, поэтому возьмите это с крошкой соли. Кроме того, я не проверял код, кроме проверки его компиляции.
Вот где я бы начал:
auto test()
{
std::condition_variable cv{};
std::mutex m{};
Process p{};
bool isRunning{true};
std::thread th([&] {
p.execute();
{
std::lock_guard<std::mutex> lk{m};
isRunning = false;
}
cv.notify_one();
});
{
std::unique_lock<std::mutex> lk{m};
// expect timeout
Assert::isFalse(cv.wait_for(lk, std::chrono::milliseconds(300),
[&] () { return !isRunning; }));
}
p.terminate();
{
std::unique_lock<std::mutex> lk{m};
// expect condition to change
Assert::isTrue(cv.wait_for(lk, std::chrono::milliseconds(300),
[&] () { return !isRunning; }));
}
th.join();
}
Таким образом, вы проверяете блокировку execute
и завершение terminate
, и вы получаете больше гибкости. Если execute
рано разблокируется, вы не ждете своего полного тайм-аута, и для terminate
у вас появляется покачивание, чтобы дождаться завершения другого потока, и вы разблокируете, как только он это сделает.
Если terminate () не может остановить выполнение, будет ли продолжен поток
его выполнение после окончания этого теста?
Если terminate
не останавливает выполнение, то второе wait_for
заканчивается после тайм-аута, возвращающего false
, и активируется подтверждение. Я не знаю, какую платформу тестирования вы используете и что делает Assert
.
если он вернет выполнение к test
, тогда тест будет блокироваться на join
, пока поток не завершит
если выдается исключение, то join
не вызывается и вызывается деструктор th
, если поток еще не закончился, std::terminate
вызывается. Это можно изменить с помощью try catch
если он вызывает выход (например, вызывает std::terminate
), тогда ... ну ... ваша программа завершается независимо от
Это действительно проблема, которую вам нужно проанализировать. Все зависит от того, что вы хотите сделать, если terminate
не сможет остановить execute
в пределах вашего интервала ожидания.
если вы в порядке ожидания в test
, то все, что вам нужно сделать, это убедиться, что join
вызван. Как я уже сказал, это разрешимо с try catch
.
если вы хотите завершить текущий тест, но согласны с тем, что поток все еще продолжается, вам нужно отсоединить поток, если terminate
не удалось завершить его.
если вы хотите убить поток, тогда ... это невозможно. Вместо этого вы можете убить все приложение через std::terminate
.