TBB任务在不再进一步递归时被阻止

时间:2015-02-06 16:33:58

标签: c++ tbb

struct root: public task
{
 root(){}
 tbb::task* execute(){
   tbb::task_list l;
   tbb::task& c = *new(allocate_continuation()) tbb::empty_task;
   int count=0;
   // do what this task should do 
   while(condition){
     l.push_back(*new(c.allocate_child())root());
     ++count;
   }
   if(count){
     c.set_ref_count(count);
     c.spawn(l);
   }
   return NULL;
 }
};
main(){
  tbb::task_scheduler_init s();
  root& r = *new(tbb::task::allocate_root())root();
  tbb::task::spawn_root_and_wait(r);
  return 0;
}

嗨,我已经定义了TBB任务" root"如果满足condition循环中的while,则可以进行一些工作然后进一步递归。如果在count==0循环后while表示不需要进一步递归,那么我就不会生成更多任务。

因为root任务不需要继续更新,所以我使用tbb::empty_task作为延续任务。

问题是这样做会阻止执行。程序无法正常返回。目前,我的解决方案是:

if(!count){
  l.push_back(*new(c.allocate_child())tbb::empty_task);
  c.spawn(l);
  c.set_ref_count(1);
}

但是,我认为价格就是性能。我想知道为什么原始代码不起作用。它适用于继续任务不是空任务的另一种情况。我不太了解那里的逻辑。谢谢你的任何评论。

1 个答案:

答案 0 :(得分:0)

一个问题是,当count==0时,任务c会丢失,因为它没有子节点而且没有生成。解除分配任务的正确方法是致电tbb::task::destroy。但是,由于您将其分配为延续,因此向spawn_root_and_wait工作完成的信号的责任转移到任务c。由于任务丢失,信号也会丢失,从而导致您观察到的死锁。要有效地为count==0情况执行信令,只需返回指向此c任务的指针root::execute(),这类似于执行spawn(c)但避免额外开销用于同步。

替代方法是c.parent()->decrement_ref_count()并手动拨打destroy(c)