使用したいのは、おそらくスコープ付きスレッドのセットであり、タイムアウト後に残りのすべてのスレッドで終了を呼び出します。残念ながら、スレッド グループとスコープ スレッドを一緒に使用することはできません。
スレッド グループ クラスは、実際には非常に単純なコンテナーです。そのスレッドへのポインターがまだない場合、そのスレッドを削除することはできません。また、グループによって作成されたスレッドへのポインターを取得することもできません。クラス API もあまり提供しません。これは、あなたの状況での管理を少し妨げています。
残りのソリューションは、グループ外でスレッドを作成することに依存しており、終了直前にそれぞれのスレッドに特定のタスクを実行させます。出来た:
- グループから自分自身を削除し、
- 次に、自分自身を別のグループに追加します
管理スレッドはjoin_all
、後者のグループを呼び出し、前者と同じように動作する必要があります。
using namespace boost;
void thread_end(auto &thmap, thread_group& t1, thread_group& t2, auto &task){
task();
thread *self = thmap[this_thread::get_id()];
t1.remove_thread(&self);
t2.add_thread(&self);
}
std::map<thread::id, thread *> thmap;
thread_group trunninggroup;
thread_group tfinishedgroup;
thread *th;
th = new thread(
bind(&thread_end, thmap, trunninggroup, tfinishedgroup, bind(&print_f)));
thmap[th->get_id()] = th;
trunninggroup.add_thread(th);
th = new thread(
bind(&thread_end, thmap, trunning_group, tfinishedgroup, bind(&print_g)));
thmap[th->get_id()] = th;
trunninggroup.add_thread(th);
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
tfinishedgroup.join_all();
trunninggroup.interrupt_all();
しかし、これは、管理スレッドが実際に発生したときにスレッドの終了を実際に通知したい場合には理想的ではありません (とにかく、それが何か役に立つかどうかはわかりません)。通知を受けるための解決策は、おそらく次のとおりです。
- 上記のようにグループの移行を行います
- 次に、管理スレッドが実行している条件変数をトリガーします
timed_wait
ただし、通知された後の残り時間を追跡するために時間計算を行い、その残り時間でスリープを再開する必要があります。それは、そのタスクに使用される Duration クラスに完全に依存します。
アップデート
全体像を見て、私はまったく別のアプローチを試みます: すでに終了しているスレッドを終了することは問題ではないと思うので、それらをすべてグループに残し、グループを使用してそれらを作成します。コードはそれを示しています。
ただし、すべてのスレッドが完了するとすぐに、またはタイムアウト後に管理スレッドを起動しようとします。これは、thread_group
クラスが単独で提供するものでは実行できませんが、カスタムメイドのセマフォ、または のパッチを適用したバージョンboost::barrier
を使用して、時間指定待機を許可することで実行できます。
基本的には、グループ内のスレッドの数に 1 を加えた数 (メイン スレッド) にバリアを設定し、メイン スレッドの時間を待機させます。各ワーカー スレッドはその作業を行い、終了すると、その結果をキューとwait
バリアに投稿します。すべてのワーカー スレッドがタスクを完了すると、全員が待機し、バリアがトリガーされます。
次に、メイン スレッド (他のすべてのスレッドと同様ですが、問題ではありません) が起動し、グループを終了して処理を続行し、結果を処理できます。それ以外の場合は、タイムアウト時に起動され、とにかく同じことを行います。
のパッチ適用はboost::barrier
それほど難しくないはずです。メソッドを複製し、内部wait
の条件変数を a に置き換えるだけで済みます(コードは見ていませんが、この仮定は完全に的を射ているかもしれません)。それ以外の場合は、この質問に対してサンプルのセマフォ実装を提供しましたが、パッチも難しくありません。wait
timed_wait
最後の考慮事項: 通常、スレッドを終了することは最善の方法ではありません。代わりに、中断する必要があるスレッドにシグナルを送って待機するか、何らかの方法で、未完了のタスクを補助スレッドに渡して、順次クリーンアップする必要があります。その後、スレッド グループは次のタスクに取り組む準備が整い、スレッドを常に破棄して作成する必要がなくなります。これは、多少コストのかかる操作です。アプリケーションのコンテキストでタスクの概念を形式化し、新しいタスクを取得して処理するためにスレッドをループで実行する必要があります。