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_count
usesk
as its argument. There is no extra 1, as there is in blocking style.Each child task except for
t1
is allocated byc.allocate_child
. It is critical to usec.allocate_child
and not(*this).allocate_child;
otherwise, the task graph will be wrong.Task
t1
is 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.
Get Intel Threading Building Blocks now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.