线程构建块(TBB)使用lambda为任务排队



TBB文档给出了在parallel_for中使用lambda表达式的示例,但没有提供在tbb::task::enqueue中使用lambda表达式的示例。

我正在寻找具有lambda表达式的tbb::task::enqueue的简单示例。

TBB中的低级任务不直接支持lambda表达式。但是,通过一些额外的编码,您可以创建语法糖助手来完成您想要的操作。

您需要创建一个调用给定函子的任务类:

template<typename F>
class lambda_task : public tbb::task {
    F my_func;
    /*override*/ tbb::task* execute() {
        my_func();
        return NULL;
    }
public:
    lambda_task( const F& f ) : my_func(f) {}
};

然后,您需要创建一个函数模板,该模板接受一个函子/lambda,将其包装到lambda_task中,并排队:

template<typename F>
void tbb_enqueue_lambda( const F& f ) {
    tbb::task::enqueue( *new( tbb::task::allocate_root() ) lambda_task<F>(f) );
}

然后你可以使用这个函数和lambda表达式:

tbb_enqueue_lambda( []{ /* code here */ } );

支持lambda表达式的官方TBB API类,如task_grouptask_arena,在内部使用非常相似的代码。


更新:传递一个函数指针和用来调用它的参数,上面的方法可以在某些方面进行扩展:

  • 在c++ 03中,您需要为具有一个参数,两个参数等的任务添加单独的类模板,并相应地重载tbb_enqueue_lambda函数
  • 在c++ 11中,您可以使用可变模板,将实际参数存储在std::tuple中的lambda_task中,并为函数调用"解包"这些参数。拆包不是一件小事,但是已经有一些主题涵盖了这一点:如何将元组扩展为可变模板函数的参数?,等。

最新更新