2012-12-15 10 views

答えて

22

できません。

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

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

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

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

std::thread::native_handleは、割り込みをサポートするかもしれないプラットフォーム固有の基本的なスレッドハンドルにアクセスすることができますが、この方法ではコードが移植不可能になり、おそらくどのようにもきれいになりません。

34

@ bamboonの回答は良いですが、これは強い声明に値すると思います。

あなたが使用する言語が何であれ、あなたのプログラムはリソース、メモリ、ファイルディスクリプタを取得し、解放するでしょう。一発で起動される単純なプログラムの場合、漏れたリソースはあまり重要ではありません。リソースを取り戻す。長期実行プログラムの場合、基本的な要件はリソースをリークさせることではなく、少なくとも繰り返しはしません。

したがって、あなたがリソースを取得するときに、それが一点で解放されていることを確認する必要があること初めから教えられてきたはずです。自分自身に質問をする、だから、

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

    /* do something */ 

    free(array); 
} 

  • 私はプログラムを殺すとどうなりますか?
  • スレッドを削除するとどうなりますか?

まあ、プログラムの終了時にOSがそうあなたが別のシステム上、または、このシステムがうまくそのリソースを取得していなかったと仮定して(これは、いくつかの仮定である)、バックリソースを収集し、我々が言ったようにそのような虐待から保護され、害もなく、汚れもない。

しかし、スレッドを強制終了すると、プログラムはまだ実行されるため、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 
    

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

  • +5

    +1、** this **はこのような重要な概念です。スレッドは、プロセスとは異なるリソースとセキュリティドメインにあります。彼らは、「敵対的」アプローチではなく、協調的アプローチを必要としている。スレッドが要求されたときに正常に終了できるように、コードをリファクタリングします。 –

    +1

    '/ * do something */'の途中で中断チェックをしてもまだ間違っている場合、' void foo(int) 'はすでに例外セーフではありません。 –

    +0

    どのような信号ですか?あなたは中断について例外を投げることについて話しています、そして、いくつかのプラットフォームはpthread_cancelに対しても同じことをします。例外がスローされた場合、関数は終了しません。 –

    関連する問題