# Recycling

Not only can you bypass the scheduler, you might also bypass task allocation and deallocation. The opportunity frequently arises for recursive tasks that do scheduler bypass. Consider the example in the Scheduler Bypass section. After it creates continuation task "`c`", it performs the following steps:

1. Create child task "`a`".

2. Create and spawn child task "`b`"

3. Return from method `execute()` with pointer to task "`a`".

4. Destroy parent task.

Recycling the parent as "`a`" can avoid the task creation destruction done by steps 1 and 4. Furthermore, in many scenarios step 1 copies state from the parent. Recycling the parent as task "`a`" eliminates the copying overhead.

The following code shows the changes required to implement recycling in the scheduler-bypass example.

    struct FibTask: public task {
        long n;
        long* sum;
        ...
        task* execute() {
            if( n<CutOff ) {
                *sum = SerialFib(n);
                return NULL;
            } else {
                FibContinuation& c =
                    *new( allocate_continuation() ) FibContinuation(sum);
                // FibTask& a = *new( c.allocate_child() ) FibTask(n-2,&c.x); This line removed
                FibTask& b = *new( c.allocate_child() ) FibTask(n-1,&c.y);
                recycle_as_child_of(c);
                n -= 2;
                sum = &c.x;
                // Set ref_count to "two children".
                c.set_ref_count(2);
                spawn( b );
                // return &a; This line removed
                return this;
            }
        }
    };

The child that was previously called `a` is now the recycled `this`. The call `recycle_as_child_of(c)` has several effects:

- It marks `this` as to not be automatically destroyed when `execute()` returns.

- It sets the successor of `this` to be `c`.

To prevent reference-counting problems, `recycle_as_child_of` has a prerequisite that `this` must have a NULL successor. This is the case after `allocate_continuation` occurs. The following figure shows how `allocate_continuation` and `recycle_as_child_of` transform the task graph.

Action of `allocate_continuation` Followed By `recycle_as_child_of`

When recycling, ensure that the original task’s fields are not used after the task might start running. The example uses the scheduler bypass trick to ensure this. You can spawn the recycled task instead, as long as none of its fields are used after the spawning. This restriction applies even to any `const` fields, because after spawning the task might run and be destroyed before the parent progresses any further.

### Note

A similar method, `task::recycle_as_continuation()` recycles a task as a continuation instead of a child.

Parent topic: Useful Task Techniques

## See Also

Scheduler Bypass