2011-11-02 60 views
0

我试图通过TBB任务和延续遍历一棵树。代码如下。当我运行代码时,它一直中止(经常,虽然不总是),但出现以下错误:TBB任务分配断言

Assertion t_next->state()==task::allocated failed on line 334 of file ../../src/tbb/custom_scheduler.h Detailed description: if task::execute() returns task, it must be marked as allocated

什么能导致这个问题?

template<class NodeVisitor> 
void 
traverse_tree(NodeVisitor& nv) 
{ 
    TreeTraversal<NodeVisitor>& tt = *(new(task::allocate_root()) TreeTraversal<NodeVisitor>(nv)); 
    task::spawn_root_and_wait(tt); 
} 

template<class NodeVisitor> 
class TreeTraversal: public task 
{ 
    public: 
     struct Continuation; 

    public: 
        TreeTraversal(NodeVisitor nv_): 
         nv(nv_)          {} 

     task*  execute() 
     { 
      nv.pre(); 

      Continuation* c = new(allocate_continuation()) Continuation(nv); 
      c->set_ref_count(nv.size()); 
      for (size_t i = 0; i < nv.size(); ++i) 
      { 
       TreeTraversal& tt = *(new(c->allocate_child()) TreeTraversal(nv.child(i))); 
       spawn(tt); 
      } 

      if (!nv.size()) 
       return c; 

      return NULL; 
     } 

    private: 
     NodeVisitor  nv; 
}; 

template<class NodeVisitor> 
class TreeTraversal<NodeVisitor>::Continuation: public task 
{ 
    public: 
         Continuation(NodeVisitor& nv_): 
          nv(nv_)        {} 
     task*   execute()        { nv.post(); return NULL; } 

    private: 
     NodeVisitor  nv; 
}; 
+0

你在原地使用新的,但你永远不会销毁,所以不会调用析构函数。我不知道这是否是问题。 –

+0

我认为TBB应该照顾这种破坏。然而,我可能是错的。 – foxcub

+0

除了查看你的代码外,我对TBB一无所知。这是可能的。 –

回答

1

我以前从未见过任务分配为延续,然后从​​返回。这可能是断言失败的原因(更新:实验显示它不是,请参阅下面的详细信息)。

同时,您可以更改代码的TreeTraversal::execute()是大致是这样的:

nv.pre(); 
if (!nv.size()) 
    nv.post(); 
else { 
    // Do all the task manipulations 
} 
return NULL; 

更新:如下图所示的简化测试我的双核笔记本电脑运行良好。这让我想到在你的实际代码中可能会发生内存破坏,在这种情况下,上面提到的重新洗牌可能只是隐藏了问题,但没有解决问题。

#include "tbb/task.h" 
using namespace tbb; 

class T: public task { 
public: 
    class Continuation: public task { 
    public: 
     Continuation() {} 
     task* execute() { return NULL; } 
    }; 

private: 
    size_t nv; 

public: 
    T(size_t n): nv(n) {} 

    task* execute() { 
     Continuation* c = new(allocate_continuation()) Continuation(); 
     c->set_ref_count(nv); 
     for (size_t i = 0; i < nv; ++i) { 
      T& tt = *(new(c->allocate_child()) T(nv-i-1)); 
      spawn(tt); 
     } 
     return (nv==0)? c : NULL; 
    } 
}; 

int main() { 
    T& t = *new(task::allocate_root()) T(24); 
    task::spawn_root_and_wait(t); 
    return 0; 
} 
+0

这就像一个魅力!非常感谢你。 – foxcub