@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
これで、適切な場所で割り込みのチェックをスレッドコードに振りかけることができます。
できません。
std::threads
は中断できません。この機能を提供するboost::thread
を使用できます。
Boostは、スレッドが中断されてそのようなポイントに到達した場合にスレッドが終了する「割り込みポイント」を定義することでこれを行います。
それでも、ほとんどの場合、再設計について考えることは、達成しようとしているものに到達するための最もクリーンで簡単な方法かもしれません。
割り込み可能なスレッドのC++ 11実装をまだ探している場合は、Anthony Williams(ブーストスレッドの所有者)の本「C++ Concurrency in Action」をご覧ください。彼は、そのようなことをどのように達成できるかについての基本的な実装を行っています。
std::thread::native_handle
を使用すると、割り込みをサポートする可能性のあるプラットフォーム固有の基礎となるスレッドハンドルにアクセスできますが、このアプローチではコードが移植不能になり、おそらくクリーンではなくなります。