您想要使用的可能是一组范围线程,并在超时后对所有剩余线程调用终止。不幸的是,线程组和作用域线程不能一起使用。
线程组类实际上是一个非常简单的容器:如果您还没有指向它的指针,则无法删除它的线程,并且您无法获得指向已由组创建的线程的指针。类 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
允许定时等待的修补版本来完成。
基本上,您为组中的线程数加一(主线程)设置障碍,并让主线程时间等待它。每个工作线程完成其工作,完成后,将其结果发布到队列和wait
屏障上。如果所有工作线程都完成了他们的任务,每个人都会等待并触发屏障。
然后主线程(以及所有其他线程,但没关系)唤醒并可以通过终止组并处理结果来继续。否则,它将在超时时被唤醒并做同样的事情。
的补丁boost::barrier
应该不会太难,你应该只需要复制wait
方法并将里面的条件变量替换为wait
a timed_wait
(我没有看代码,这个假设可能完全有道理)。否则,我为这个问题提供了一个示例信号量实现,也应该不难修补。
最后一点考虑:终止线程通常不是最好的方法。相反,您应该尝试向它们发出中止线程的信号,并等待它们,或者以某种方式让它们将未完成的任务传递给应该连续清理的辅助线程。然后,您的线程组将准备好处理下一个任务,并且您不必一直销毁和创建线程,这是一项代价高昂的操作。它将需要在应用程序的上下文中形式化任务的概念,并使线程在循环上运行以获取新任务并处理它们。