Я хочу убить std :: thread, используя его объект thread?

Возможный дубликат:
C ++ 0x прерывание потока

Я пытаюсь убить / остановить c ++ std :: thread, используя его объект потока.

Как мы можем это сделать?

26

Решение

Ответ @ 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

Теперь вы можете просто посыпать свой многопоточный код проверками на прерывание в соответствующих местах.

38

Другие решения

Ты не можешь

std::threads не прерываются Ты можешь использовать boost::thread который предлагает эту функцию.

Boost делает это, определяя «точки прерывания», в которых поток завершится, если он прервется и достигнет такой точки.

Тем не менее, большую часть времени размышления о редизайне могут быть самым чистым и простым способом достижения того, чего вы пытаетесь достичь.

Если вы все еще ищете реализацию прерывистых потоков на C ++ 11, посмотрите книгу Энтони Уильямса (владельца Boost Thread) «Параллельность C ++ в действии». Он проходит базовую реализацию того, как такая вещь может быть достигнута.

std::thread::native_handle дает вам доступ к дескриптору основного потока конкретной платформы, который может поддерживать прерывание, однако такой подход делает ваш код непереносимым и, вероятно, не чище.

25

По вопросам рекламы [email protected]