web-dev-qa-db-ja.com

スレッドオブジェクトを使用してstd :: threadを強制終了したいですか?

可能性のある複製:
C++ 0xスレッド割り込み

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

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

26
CPS

@bamboonの答えは良いですが、これはより強力な声明に値すると思います。

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

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

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

    /* do something */

    free(array);
}

だから、質問を自問してください:

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

さて、私たちが言ったように、プログラムが終了すると、OSはリソースを収集します。そのため、another system ORこのシステムは、このような乱用、害、汚損に対して十分に保護されています。

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

高レベル言語にはこれを処理する方法があります:例外です。とにかくプログラムは例外セーフでなければならないので、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

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

39
Matthieu M.

できません。

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

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

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

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

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

27
inf