Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

@bamboon ответ хорош, однако я считаю, что это заслуживает более сильного заявления.

Независимо от того, какой язык вы используете, ваша программа будет приобретать и выпускать ресурсы: память, файловые дескрипторы,... Для простых программ, которые запускаются в один кадр, утечка ресурсов не имеет большого значения: когда программа заканчивается, современные ОС автоматически принимают ресурсы обратно; однако для долгосрочных программ основным требованием является не утечка ресурсов или, по крайней мере, нерегулярно.

Поэтому вам следует с самого начала учиться, что, когда вы приобретаете ресурс, вам нужно будет обеспечить его освобождение в какой-то момент:

void foo(int i) {
    int* array = malloc(sizeof(int) * i);

    /* do something */

    free(array);
}

Итак, задайте себе вопрос:

  • что происходит, когда я убиваю программу?
  • что происходит, когда я убиваю поток?

Ну, как мы сказали, когда программа заканчивается, ОС собирает ресурсы обратно, поэтому, предполагая (и это некоторые предположения), что вы не приобрели ресурс в другой системе или что эта система хорошо защищена от такого злоупотребления, нет вреда, нет фола.

Однако, когда вы убиваете поток, программа все еще работает, поэтому ОС не собирает ресурсы обратно. Вы пропустили память, вы заблокировали файл для записи, который вы больше не можете разблокировать,... Вы не должны убивать потоки.

Языки более высокого уровня имеют способ справиться с этим: исключения. Поскольку программы в любом случае должны быть безопасными для исключения, Java (например) уничтожит поток, приостанавливая его, бросая исключение в момент выполнения и аккуратно разматывая стек. Однако на С++ такого объекта нет.

Это невозможно? Нет, очевидно, нет. Собственно, вы могли бы полностью использовать ту же самую идею:

  • encapsulate 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

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

Ответ 2

Вы не можете.

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

Boost делает это, определяя "точки прерывания", по которым поток заканчивается, если он прерывается и достигает такой точки.

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

Если вы все еще ищете реализацию проверки прерывистых потоков на С++ 11 Энтони Уильямса (владелец ускоренного потока), книга "С++ Concurrency в действии". Он проводит базовую реализацию того, как это можно достичь.

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