Возможный дубликат:
прерывание потока C++0x
Я пытаюсь убить/остановить С++ std::thread, используя его объект потока.
Как мы можем это сделать?
Возможный дубликат:
прерывание потока C++0x
Я пытаюсь убить/остановить С++ std::thread, используя его объект потока.
Как мы можем это сделать?
Ответ @bamboon хорош, однако я считаю, что он заслуживает более сильного утверждения.
Какой бы язык вы ни использовали, ваша программа будет получать и освобождать ресурсы: память, файловые дескрипторы, ... Для простых программ, которые запускаются одним выстрелом, утечка ресурсов не имеет большого значения: когда программа завершается, современные ОС автоматически забирают ресурсы обратно. ; однако для долго работающих программ основным требованием является отсутствие утечки ресурсов или, по крайней мере, повторения.
Поэтому вас с самого начала должны были научить тому, что когда вы приобретаете ресурс, вы должны обеспечить его освобождение в какой-то момент:
void foo(int i) {
int* array = malloc(sizeof(int) * i);
/* do something */
free(array);
}
Итак, задайте себе вопрос:
Что ж, как мы уже говорили, когда программа завершается, ОС собирает ресурсы обратно, поэтому предполагается (и это некоторое предположение), что вы не получили ресурс в другой системе ИЛИ что эта система хорошо защищена. против такого злоупотребления, ни вреда, ни фола.
Однако, когда вы завершаете поток, программа продолжает работать, поэтому ОС не собирает ресурсы обратно. У вас произошла утечка памяти, вы заблокировали файл для записи, который вы больше не можете разблокировать, ... Вы не должны убивать темы.
В языках более высокого уровня есть способ справиться с этим: исключения. Поскольку программы в любом случае должны быть защищены от исключений, Java (например) уничтожит поток, приостановив его, бросив исключение в точке выполнения и аккуратно размотав стек. Однако в C++ такой возможности пока нет.
Это невозможно? Нет, очевидно, нет. На самом деле, вы могли бы прекрасно использовать ту же самую идею:
std::thread
, класс interruptible_thread
также будет содержать флаг прерыванияstd::thread
при его запуске и сохраните его локальным способомЭто:
// Synopsis
class interrupt_thread_exception;
class interruptible_thread;
void check_for_interrupt();
// Interrupt exception
class interrupt_thread_exception: public virtual std::exception {
public:
virtual char const* what() const override { return "interrupt"; }
}; // class interrupt_thread_exception
// Interruptible thread
class interruptible_thread {
public:
friend void check_for_interrupt();
template <typename Function, typename... Args>
interruptible_thread(Function&& fun, Args&&... args):
_thread([](std::atomic_bool& f, Function&& fun, Args&&... args) {
_flag_ref = &f; fun(std::forward<Args>(args)...);
},
_flag,
std::forward<Function>(fun),
std::forward<Args>(args)...)
{}
bool stopping() const { return _flag.load(); }
void stop() { _flag.store(true); }
private:
static thread_local std::atomic_bool* _flag_ref = nullptr;
std::atomic_bool _flag = false;
std::thread _thread;
}; // class interruptible_thread
// Interruption checker
inline void check_for_interrupt() noexcept(false) {
if (not interruptible_thread::_flag_ref) { return; }
if (not interruptible_thread::_flag_ref->load()) { return; }
throw interrupt_thread_exception();
} // check_for_interrupt
Теперь вы можете просто посыпать свой многопоточный код проверками на прерывание в соответствующих местах.
void foo(int)
уже не является безопасным для исключений, если у вас есть проверка прерывания в середине `/* сделать что-то */', это все равно будет неправильно.
- person Jonathan Wakely; 16.12.2012
try/catch
блоки, RAII и т. д., тогда как грубое прерывание оставляет вам не инструмент для очистки. Обратите внимание, что я сказал проверки прерываний в соответствующих местах.! И вы по-прежнему можете прерывать foo, пока вы перехватываете исключение, так что free
выполняется... но на самом деле это не имелось в виду, я больше демонстрировал необходимость очистки явно, в то время как Хорошо построенная программа на C++, очевидно, будет использовать RAII.
- person Matthieu M.; 16.12.2012
terminate()
в boost::thread использует в целом аналогичный подход. Их терминология: точки прерывания. Преимущество boost::thread по сравнению с приведенным выше кодом: boost::thread также имеет встроенную поддержку прерывания спящих операций. Например. из boost::thread::sleep_for().
- person Nanno Langstraat; 12.12.2013
getline
. И нет стандартного способа сделать это неблокирующим способом.
- person Simon; 22.03.2014
Вы не можете.
std::threads
нельзя прервать. Вы можете использовать boost::thread
, который предлагает эту функцию.
Boost делает это, определяя «точки прерывания», на которых завершится поток, если он будет прерван и достигнет такой точки.
Тем не менее, в большинстве случаев размышления о редизайне могут быть самым чистым и простым способом достичь того, чего вы пытаетесь достичь.
Если вы все еще ищете реализацию прерываемых потоков на С++ 11, ознакомьтесь с книгой Энтони Уильямса (владельца потока повышения) "C++ Concurrency in Action". Он проходит базовую реализацию того, как такая вещь может быть достигнута.
std::thread::native_handle
дает вам доступ к базовому дескриптору потока для конкретной платформы, который может поддерживать прерывание, однако такой подход делает ваш код непереносимым и, вероятно, никоим образом не чище.