Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

enqueue bug or lack of documentation


Good afternoon

I think there's a bug in the enqueue operation or at least a lack of documentation. I also think that the behaviour there has changed recently and it had not been an issue with previous versions of TBB. If you call enqueue on a task allocated as root, it inherits the task group context. If the original root task that has "opened" this task group context terminates, the task context seems to be destroyed even though there still are some tasks enqueued. It leads to

Assertion tgc->my_cancellation_requested == 0 || tgc->my_cancellation_requested == 1 failed on line 443 of file ../../src/tbb/scheduler.h
Detailed description: task_group_context is invalid                                                                                                                                                                                                                            

(or a seg fault if you forget to link to tbb_malloc). I'm not sure whether this behaviour of the task context is correct. The workaround is obvious once you are aware of the problem:

static tbb::task_group_context  mycontext;

Task* tbbTask = new(tbb::task::allocate_root(mycontext)) MyFancyTask();


But I think this at least deserves a comment in enqueue. Instead, one could make enqueue always create its own context or ensure that the surrounding context is not destroyed if any tasks still is enqueued.



0 Kudos
1 Reply


I am sorry that you observed this complicated issue. It is not the issue of tbb::task::enqueue; however, the semantics of tbb::task::enqueue leads to error-prone approaches. According to the documentation of the tbb::task_group_context:


Destroys an empty task_group_context. It is a programmer error if there are still extant tasks in the group.

As you already mentioned, tbb::task_group_context (cancellation group) is captured by tbb::task:allocate_root:

new( task::allocate_root() ) T

Like new(task::allocate_root(task_group_context&)) except that cancellation group is the current innermost cancellation group.

So, you can observe the same issue with a spawned task; however, it is usually used with tbb::task::spawn_root_and_wait interface that forces the task to be executed before the scope is closed and the context is destroyed.

The Intel TBB Task Scheduler interface is very complicated and has many particularities that has to be considered to implement the correct algorithm. We usually recommend using high level parallel algorithms (e.g. tbb::parallel_fortbb::task_grouptbb::flow::graph and others) if possible. Feel free to describe your algorithm that we can try to consider a solution without explicit tasks or recommend some techniques to avoid errors in future.

Regards, Alex

0 Kudos