# Yield functionality

## Introduction

The yield functionality will allow reflows to interrupt after a certain predefined time. Reflows are typically preceded by a traverse operation, and all traverse operations allowing yield must be able to handle an failure with OpStatus::ERR_YIELD.

A typical response to a OpStatus::ERR_YIELD signal is to try with the operation again after returning to the message loop.

## Overview

## Details

### Enabling yield

#### Globally

Yield is controlled by two prefs:

Initial Yield Reflow Time
  "0" means that yield is completely turned off. Any other (positive) value means the number of milliseconds allowed before yielding.
Yield Reflow Time Increase Rate
  Controls the rate that the yield time will increase if it is not possible to leave from the yield loop. The yield time will double after this many failed reflow tries

#### Code perspective

Every traverse operation will need to tell the LayoutWorkplace that it is able to handle the OpStatus::ERR_YIELD signal. This is done by calling LayoutWorkplace::SetCanYield(TRUE) before the traverse, and LayoutWorkplace::SetCanYield(FALSE) after the traverse.

### Yield thrown

A yield is thrown from Box::LayoutChildren before the children are laid out. The reflow saves the cascade and the yield-from element and leaves an OpStatus::ERR_YIELD signal.

### Yield recover

There are two ways to recover from a yield action, depending on if the tree changed after the yield was thrown.

#### Unchanged tree

If the tree is unchanged between the yield and the recovery, the cascade used when yielding may be reused, which will not make it a bug performance hit. This is done by using the "first_child" argument in the layout operations. This will just bypass any Layout calls, just maintaing the cascade, until the first child is reached, and continue reflowing from there.

#### Changed tree

If the tree changed in any way, (including loading operations) we must dismount the yield cascade and mark the yield element dirty. This will be a performance hit.

### specialities

#### layout_changed flag

The LayoutInfo::layout_changed flag says that we must reflow all children, since a float may have spilled over it's box on a completely different branch. This flag needs to be maintained.

In the unchanged tree case, this is rather simple, we just need to make sure the LayoutInfo::layout_changed flag is set to the same value as before the yield.

If the tree changed we need to find the topmost element that caused this layout_changed flag to be set, and enable it from where this element is reflowed.

#### generated content

Yielding is not allowed inside generated content elements, or (exactly) on elements inserted by layout.

## Possible improvements