void RenderNamedFlowThread::removeRegionFromThread(RenderRegion* renderRegion)
{
    ASSERT(renderRegion);

    RenderNamedFlowFragment* renderNamedFlowFragment = toRenderNamedFlowFragment(renderRegion);
    if (renderNamedFlowFragment->parentNamedFlowThread()) {
        if (!renderNamedFlowFragment->isValid()) {
            ASSERT(m_invalidRegionList.contains(renderNamedFlowFragment));
            m_invalidRegionList.remove(renderNamedFlowFragment);
            renderNamedFlowFragment->parentNamedFlowThread()->m_observerThreadsSet.remove(this);
            // No need to invalidate the regions rectangles. The removed region
            // was not taken into account. Just return here.
            return;
        }
        removeDependencyOnFlowThread(renderNamedFlowFragment->parentNamedFlowThread());
    }

    ASSERT(m_regionList.contains(renderNamedFlowFragment));
    bool wasFirst = m_regionList.first() == renderNamedFlowFragment;
    m_regionList.remove(renderNamedFlowFragment);

    if (canBeDestroyed())
        setMarkForDestruction();

    if (!m_regionList.isEmpty() && wasFirst)
        updateWritingMode();

    invalidateRegions();
}
void RenderNamedFlowThread::checkInvalidRegions()
{
    Vector<RenderNamedFlowFragment*> newValidFragments;
    for (auto& region : m_invalidRegionList) {
        RenderNamedFlowFragment* namedFlowFragment = toRenderNamedFlowFragment(region);
        // The only reason a region would be invalid is because it has a parent flow thread.
        ASSERT(!namedFlowFragment->isValid() && namedFlowFragment->parentNamedFlowThread());
        if (namedFlowFragment->parentNamedFlowThread()->dependsOn(this))
            continue;

        newValidFragments.append(namedFlowFragment);
    }

    for (auto& namedFlowFragment : newValidFragments) {
        m_invalidRegionList.remove(namedFlowFragment);
        namedFlowFragment->parentNamedFlowThread()->m_observerThreadsSet.remove(this);
        addFragmentToNamedFlowThread(namedFlowFragment);
    }

    if (!newValidFragments.isEmpty())
        invalidateRegions();

    if (m_observerThreadsSet.isEmpty())
        return;

    // Notify all the flow threads that were dependent on this flow.

    // Create a copy of the list first. That's because observers might change the list when calling checkInvalidRegions.
    Vector<RenderNamedFlowThread*> observers;
    copyToVector(m_observerThreadsSet, observers);

    for (auto& flowThread : observers)
        flowThread->checkInvalidRegions();
}
void RenderNamedFlowThread::addRegionToThread(RenderRegion* renderRegion)
{
    ASSERT(renderRegion);
    ASSERT(!renderRegion->isValid());

    RenderNamedFlowFragment* renderNamedFlowFragment = toRenderNamedFlowFragment(renderRegion);
    resetMarkForDestruction();

    if (renderNamedFlowFragment->parentNamedFlowThread() && renderNamedFlowFragment->parentNamedFlowThread()->dependsOn(this)) {
        // The order of invalid regions is irrelevant.
        m_invalidRegionList.add(renderNamedFlowFragment);
        // Register ourself to get a notification when the state changes.
        renderNamedFlowFragment->parentNamedFlowThread()->m_observerThreadsSet.add(this);
        return;
    }

    addFragmentToNamedFlowThread(renderNamedFlowFragment);

    invalidateRegions();
}