All right, now I see where is the problem. Functions like
allocate_additional_child_of are treaky beasts as they implicitly use another argument - "this". And it is easy to overlook the fact that "this" plays a critical role here, it establishes thread ownership for the new task. And it has a requirement to be owned by the current thread. In your example you use parent as owner, but the parent can be (and, as the corrupted memory testifies, is) owned by (running on) another thread at the moment of some of its descendants allocation.
Here is the fixed piece of code:
class leaf_task : public tbb::task
{
tbb::task* execute () {
++g_tasks_started;
for ( size_t i = 0; i < 10000; ++i )
g_vol += i/g_vol;
return NULL;
}
public:
static tbb::task* create ( tbb::task *
owner, tbb::task *parent ) {
return new(
owner->allocate_additional_child_of(*parent) ) leaf_task;
}
}; // class leaf_task
class task_launcher : public tbb::task {
tbb::task* execute(){
spawn( *leaf_task::create(
this, parent()) );
return NULL;
}
}; // class task_launcher
Important changes are in bold.
Note also that I turned the instance method "creator" into the static one. It allows you to avoid creating fake local objects to call the instance method, and makes the code cleaner. My heart nearly stopped when I saw that leaf_task object allocated on the stack
![smiley [:-)]](/isn/Community/en-US/emoticons/emotion-1.gif)
.
Andrey Marochko
TBB developer