如何重新计划并发任务



粗体的简短解释。

我有一个tbb::task可以总结为:

class UpdateTask
: public tbb::task
{
public:
    tbb::task* execute()
    {
        // some work...
        if( can_continue() )
        {
            // make sure this is re-executed
            this->recycle_to_reexecute(); //looks like it is deprecated but it's more clear to me
                            return nullptr; // ? or this? or tbb::empty_task?
        }
        return nullptr;
    }
};

我希望此任务在完成后立即重新安排,直到满足条件。我以这种方式分配此任务:

UpdateTask& updater = *new(tbb::task::allocate_root()) UpdateTask();

不确定它与问题有关。

问题:当我运行代码时,我从 tbb(最新修订版,4.1.5)获得断言(在调试中),但我找不到使其正常工作的方法。

我已经重新阅读了文档,但我找不到一个简单的例子,我也不清楚我做错了什么。我做了一些实验:

  • 使用我刚刚显示的代码,断言说我应该返回一个任务: Assertion t_next failed on line 485 of file ...itbbsrctbbcustom_scheduler.h Detailed description: reexecution requires that method execute() return another task
  • 然后,如果我返回这个,断言说应该分配任务: Assertion t_next->state()==task::allocated failed on line 452 of file ...itbbsrctbbcustom_scheduler.h Detailed description: if task::execute() returns task, it must be marked as allo cated
  • 在疑问中,我试图返回我动态创建的 tbb::empty_task(用于检查),并分配为 new(tbb::task::allocate_child()) tbb::empty_task() .我得到了这条消息的断言Assertion p.ref_count==0 failed on line 107 of file ...itbbsrctbbcustom_scheduler.h Detailed description: completion of task caused predecessor's reference count to underflow.

那么,该怎么做呢?我认为它很简单,但找不到完成的方式。它与任务引用计数有关吗?


更新:这是一个完整的代码,它很好地接近了我所拥有的内容:

#include <iostream>
#include <atomic>
#include <tbb/tbb.h>
namespace test {    class UpdateTask        : public tbb::task  {   public:
        UpdateTask()        {           std::cout << "[UpdateTask]" << std::endl;       }
        ~UpdateTask()       {           std::cout << "n[/UpdateTask]" << std::endl;        }
        tbb::task* execute()        {           std::cout << "Tick "<< m_count <<std::endl;
            ++m_count;
            // make sure this is re-executed            this->recycle_to_reexecute();           //return new(tbb::task::allocate_continuation()) tbb::empty_task();             return nullptr;         }
    private:
        std::atomic<int> m_count;
    };

    tbb::task_list m_task_list;

    void register_update_task()     {       UpdateTask& updater =
*new(tbb::task::allocate_root()) UpdateTask();      m_task_list.push_back( updater );   }
    void run_and_wait()     {       tbb::task::spawn_root_and_wait( m_task_list );  }
    void tbb_test()     {       register_update_task();         run_and_wait();
    }
}
int main()
{
    test::tbb_test();
    std::cout << "nEND";
    std::cin.ignore();
    return 0;
}

所以,这里我得到了第一个例外,说我应该返回一个任务。在execute()函数中,如果我用注释的返回替换返回,那么它似乎可以工作,但这有两个问题:

  • 每次完成要执行的调用时,我都必须创建一个empty_task任务???
  • 在第一次调用 execute() 后,主线程恢复。这不是spawn_root_and_wait()应该做的。在所有任务未完成并正确重新安排后。

我必须得出结论,这也不是正确的方法。

this->recycle_to_reexecute();

已弃用。

替换为

this->increment_ref_count();
this->recycle_as_safe_continuation();

享受

附言:结束当然(在你的例子中)从执行返回 NULL

最新更新