如果在函数中使用tbb::task::enqueue
将任务排入队列,然后在执行任务之前函数超出范围,那么任务是否会丢失?
如果是这样,怎么可以避免?例如,如果您想要在短期事件处理程序回调中将任务排入队列,这将很快超出范围,而调度程序将在稍后执行该任务?
此外,enqueue
功能是否有容量限制?如果超过一定数量的待处理数量会丢弃任务吗?
答案 0 :(得分:2)
tbb::task
是一个对象。相同的C ++生存期规则(和危险!)适用于tbb::task
和任何其他C ++对象。对于相关案例,请务必以不会受返回函数影响的方式捕获任务中的信息。例如,捕获局部变量的值,而不是引用。
这是一个使用lambda表达式显示问题的程序。它借用了Alexey Kukanov's lambda_task
#include <tbb/tbb.h>
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) {}
};
template<typename F>
void tbb_enqueue_lambda( const F& f ) {
tbb::task::enqueue( *new( tbb::task::allocate_root() ) lambda_task<F>(f) );
}
void LaunchOneTask( int i, int j ) {
if( i%1000000==0 )
[i,&j]{printf("Launching i=%d j=%d\n",i,j);}();
tbb_enqueue_lambda( [i,&j]{ // Deliberate mistake for j!
printf("Hi from lambda: i=%d j=%d\n",i,j);
sleep(1);
} );
}
int main() {
for( int i=0; i<1000000000; ++i ) {
LaunchOneTask(i,i);
}
}
如果你运行它,你会看到&#34;启动......&#34;行正确打印i
和j
,但是&#34; Hi来自...&#34;行打印j
的错误值。这是因为lambda已经通过引用(j
)捕获了&j
,并且引用了一个在任务运行之前消失的左值。
据我所知,tbb::task::enqueue
的容量限制是系统内存的容量限制。它取决于程序员,以确保不会发生这种情况。