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.
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.
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.
There are two ways to recover from a yield action, depending on if the tree changed after the yield was thrown.
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.
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.
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.