1

If you use tbb::task::enqueue in a function to enqueue a task, and then the function goes out of scope before the task is executed, will the task get lost?

If so, how could that be avoided? For example, what if you want to enqueue a task in a short-lived event handler callback which will go out of scope quickly, whereas the task will not be executed by the scheduler until somewhat later?

Furthermore, does the enqueue function have a capacity limit? Will it drop tasks if there are more than a certain number pending?

Cosmo Harrigan
  • 895
  • 1
  • 8
  • 22

1 Answers1

2

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.

Community
  • 1
  • 1
Arch D. Robison
  • 3,829
  • 2
  • 16
  • 26