I'm writing a benchmark making use of tbb tasks spawned largely with the "allocate_additional_child_of(...)" command, due to not knowing how many tasks to spawn until runtime. Currently I performan set_ref_count(1), then in a loop perform as many allocates and spawns as necessary, then doing a wait_for_all. This seems to run fine for small numbers of tasks, but if I start getting into larger values (thousands), I begin to get random assertion failures, the most common of which is "another thread emptied the return_list."
Due to getting different assertion failures for the same command line arguments, I assumed it was a memory corruption issue, and have tried tracing it down with both microsoft's debug heap and OSX's guardmalloc, both of which haven't found anything (on the contrary, the benchmark runs without problem when using malloc debug tools, possibly due to the slowdown removing any race conditions).
Is there any information on what this return_list is? The assertion fails when I try to spawn another task using allocate_additional_child_of(*this), but I'm not sure what it means. Other assertions that pop up tend to do with "small_task_count corrupted" and "attempt to spawn task that is not in allocated state", even though I only spawn tasks immediately after allocating them. Perhaps how I'm spawning tasks isn't correct? Hopefully understanding this return_list may help me trace down the issue.
This discussion inspired me to upgrade my implementation of task_group on http://softwareblogs.intel.com/2008/07/02/implementing-task_group-interface-in-tbbto allow multiple threads to create tasks within the same task_group. I used task::self() for the "owner". It depends upon an undocumented implementation feature that when there is no running task ona master thread, nonetheless task::self() returns a reference to a dummy task owned by that thread.