A tbb::task
is an object. The same C++ lifetime rules (and hazards!) apply to tbb::task
as any other C++ object. For the case in question, be sure to capture information in the task in a way that won't be affected by the function returning. For example, capture values, not references, of local variables.
Here is a program that shows the issue, using lambda expressions. It borrows 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);
}
}
If you run it, you'll see that the "Launching..." lines print i
and j
correctly, but the "Hi from..." lines print the wrong value for j
. This is because the lambda has captured j
by reference (&j
), and the reference is to an lvalue that disappears before the task runs.
As far as I know, the capacity limit on tbb::task::enqueue
is the capacity limit of the system memory. It's up to the programmer to ensure that this does not happen.