重複の可能性:
C++0x スレッドの中断
スレッド オブジェクトを使用して c++ std::thread を強制終了/停止しようとしています。
どうすればこれを行うことができますか?
@bamboonの答えは良いですが、これはもっと強力な発言に値すると思います。
使用する言語に関係なく、プログラムはリソースを取得して解放します:メモリ、ファイル記述子、...ワンショットで起動される単純なプログラムの場合、リソースのリークはそれほど重要ではありません。プログラムが終了すると、最新のOSは自動的にリソースを取り戻します。 ; ただし、長時間実行されるプログラムの場合、基本的な要件は、リソースをリークしないこと、または少なくとも繰り返し実行しないことです。
したがって、リソースを取得するときは、ある時点で確実に解放する必要があることを最初から教えておく必要があります。
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
これで、適切な場所での割り込みのチェックをスレッドコードに振りかけることができます。
できません。
std::threads
中断できません。boost::thread
この機能を提供するものを使用できます。
Boostは、スレッドが中断されてそのようなポイントに到達した場合にスレッドが終了する「中断ポイント」を定義することによってこれを行います。
それにもかかわらず、ほとんどの場合、再設計について考えることは、あなたが達成しようとしていることに到達するための最もクリーンで簡単な方法かもしれません。
割り込み可能なスレッドのC++11実装をまだ探している場合は、Anthony Williams(ブーストスレッドの所有者)の本「C ++ConcurrencyinAction」をチェックアウトしてください。彼は、そのようなことをどのように達成できるかについての基本的な実装を経験します。
std::thread::native_handle
割り込みをサポートする可能性のあるプラットフォーム固有の基盤となるスレッドハンドルにアクセスできますが、このアプローチではコードが移植不可能になり、おそらくクリーンではなくなります。