29

重複の可能性:
C++0x スレッドの中断

スレッド オブジェクトを使用して c++ std::thread を強制終了/停止しようとしています。

どうすればこれを行うことができますか?

4

2 に答える 2

42

@bamboonの答えは良いですが、これはもっと強力な発言に値すると思います。

使用する言語に関係なく、プログラムはリソースを取得して解放します:メモリ、ファイル記述子、...ワンショットで起動される単純なプログラムの場合、リソースのリークはそれほど重要ではありません。プログラムが終了すると、最新のOSは自動的にリソースを取り戻します。 ; ただし、長時間実行されるプログラムの場合、基本的な要件は、リソースをリークしないこと、または少なくとも繰り返し実行しないことです。

したがって、リソースを取得するときは、ある時点で確実に解放する必要があることを最初から教えておく必要があります。

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

    /* do something */

    free(array);
}

だから、あなた自身に質問をしてください:

  • プログラムを強制終了するとどうなりますか?
  • スレッドを強制終了するとどうなりますか?

さて、私たちが言ったように、プログラムが終了すると、OSはリソースを回収します。したがって、別のシステムでリソースを取得していない、またはこのシステムがそのような悪用から十分に保護されていると仮定すると(これはいくつかの仮定です)、害はありません、ファウルはありません。

ただし、スレッドを強制終了してもプログラムは実行されるため、OSはリソースを回収しません。メモリリークが発生し、書き込み用にファイルをロックしたため、ロックを解除できなくなりました...スレッドを強制終了してはなりません

高水準言語にはこれを処理する方法があります:例外。プログラムはとにかく例外安全である必要があるため、Java(たとえば)はスレッドを一時停止し、実行時に例外をスローして、スタックを穏やかに巻き戻します。ただし、C++にはまだそのような機能はありません。

それは不可能ですか?いいえ、明らかにそうではありません。実際、まったく同じアイデアを完全に再利用できます。

  • カプセル化std::threadinterruptible_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

これで、適切な場所での割り込みのチェックをスレッドコードに振りかけることができます。

于 2012-12-15T15:14:22.823 に答える
32

できません。

std::threads中断できません。boost::threadこの機能を提供するものを使用できます。

Boostは、スレッドが中断されてそのようなポイントに到達した場合にスレッドが終了する「中断ポイント」を定義することによってこれを行います。

それにもかかわらず、ほとんどの場合、再設計について考えることは、あなたが達成しようとしていることに到達するための最もクリーンで簡単な方法かもしれません。

割り込み可能なスレッドのC++11実装をまだ探している場合は、Anthony Williams(ブーストスレッドの所有者)の本「C ++ConcurrencyinAction」をチェックアウトしてください。彼は、そのようなことをどのように達成できるかについての基本的な実装を経験します。

std::thread::native_handle割り込みをサポートする可能性のあるプラットフォーム固有の基盤となるスレッドハンドルにアクセスできますが、このアプローチではコードが移植不可能になり、おそらくクリーンではなくなります。

于 2012-12-15T14:41:55.970 に答える