Recycling the parent as a child
This style is useful when the child inherits much of its state from a parent and the continuation does not need the parent’s state. The child must have the parent’s type. In Example 9-6, C is the type of the continuation, and it must derive from the class task. If C does nothing but wait for all children to complete, C can be the class empty_task.
Example 9-6. Recycling parent as a child
task* T::execute() {
if( not recursing any further ) {
...
return NULL;
} else {
set_ref_count(k);
// Construct continuation
C& c = allocate_continuation();
// Recycle self as first child
task& tk = new( c.allocate_child() ) T(…); tk.spawn();
task& tk-1 = new( c.allocate_child() ) T(…); tk-1.spawn();
...
task& t2 = new( c.allocate_child() ) T(…); t2.spawn();
// task t1 is our recycled self.
recycle_as_child_of(c);
... update fields of *this to state subproblem to be solved by t1
return this;
}
}Here are the key points of the pattern:
The call to
set_ref_countuseskas its argument. There is no extra 1, as there is in blocking style.Each child task except for
t1is allocated byc.allocate_child. It is critical to usec.allocate_childand not(*this).allocate_child;otherwise, the task graph will be wrong.Task
t1is recycled from the parent, and hence gets the parent’s state without performing copy operations. Do not forget to update the state to represent a child subproblem; otherwise, infinite recursion will occur.