int pipelineOverallPush = 0;
boolean completed;  do
    public void computeMinLatencySchedule(        PipelineSchedulingUtility utility,        int childrenExecs[],        int dataInBuffers[])    {        // reset the buffer below the pipeline (it's not actually used        // for any computation)        dataInBuffers[getNumChildren()] = 0;                // calculate how much data the pipeline is supposed to push out        // during execution of this schedule        int pipelineOverallPush = 0;        {            int lastChildIndex = getNumChildren () - 1;            StreamInterface child = getHierarchicalChild(lastChildIndex);            int nPhase = childrenExecs [lastChildIndex] - 1;            for ( ; nPhase >= 0; nPhase--)            {                PhasingSchedule phase = utility.getChildPhase(child, nPhase);                pipelineOverallPush += phase.getOverallPush();            }        }        // repeat while the last child still needs to pull some data        while (dataInBuffers[getNumChildren()] < pipelineOverallPush)        {            int numChildExecs[] = new int[getNumChildren()];            // figure out how many times each child needs to get executed            {                int nextChildDataNeeded = 1, nChild;                for (nChild = getNumChildren() - 1;                    nChild >= 0;                    nChild--)                {                    StreamInterface child = getHierarchicalChild(nChild);                    int childPeek = 0, childPop = 0;                    // repeat while still need to provide data                     // for the next child                    while (nextChildDataNeeded > 0)                    {                        // figure out how much this phase/stage will                         // push/pop/peek                        PhasingSchedule phase =                            utility.getChildPhase(                                child,                                numChildExecs[nChild]);                        int phasePeek = phase.getOverallPeek();                        int phasePop = phase.getOverallPop();                        int phasePush = phase.getOverallPush();                        // update the overall phase child peek/pop                        childPeek = MAX(childPeek, childPop + phasePeek);                        childPop += phasePop;                        // reduce the amount of data still needed                        // by the next child                        nextChildDataNeeded -= phasePush;                        // note that I just executed another stage/phase                         // of this child                        numChildExecs[nChild]++;                    }                    // figure out how much data the previous child                    // still needs to provide:                    nextChildDataNeeded =                        childPeek - dataInBuffers[nChild];                }            }            // construct an actual stage of the schedule and execute it            {                PhasingSchedule steadyPhase = new PhasingSchedule(this);                int nChild;                for (nChild = 0; nChild < getNumChildren(); nChild++)                {                    StreamInterface child = getHierarchicalChild(nChild);                    for (;                        numChildExecs[nChild] > 0;                        numChildExecs[nChild]--)                    {                        PhasingSchedule phase =                            utility.getChildNextPhase(child);                        // add this stage to the init schedule                        steadyPhase.appendPhase(phase);                        utility.advanceChildSchedule(child);                        // better have enough data in the buffer to execute                         // this phase                        ASSERT(                            nChild == 0                                || dataInBuffers[nChild]                                    >= phase.getOverallPeek());                        // adjust buffers for this child                        dataInBuffers[nChild] -= phase.getOverallPop();                        dataInBuffers[nChild                            + 1] += phase.getOverallPush();                        // mark down that this child had another phase executed                        childrenExecs[nChild]--;                    }                }                // add the init stage to the init schedule                utility.addSchedulePhase(steadyPhase);            }        }        // it is possible that I need another phase to execute clean-up        // phases of the children that don't output from the pipeline        // (all but the bottom most child)        {            PhasingSchedule extraPhase = new PhasingSchedule(this);            int nChild;            for (nChild = 0; nChild < getNumChildren(); nChild++)            {                StreamInterface child = getHierarchicalChild(nChild);                for (;                    childrenExecs[nChild] > 0;                    childrenExecs[nChild]--)                {                    PhasingSchedule phase =                        utility.getChildNextPhase(child);                    // add this stage to the init schedule                    extraPhase.appendPhase(phase);                    utility.advanceChildSchedule(child);                    // better have enough data in the buffer to execute                     // this phase                    ASSERT(                        nChild == 0                            || dataInBuffers[nChild]                                >= phase.getOverallPeek());                    // adjust buffers for this child                    dataInBuffers[nChild] -= phase.getOverallPop();                    dataInBuffers[nChild + 1] += phase.getOverallPush();                }                // make sure that I've executed every child the right number                // of phases.  if this assert goes off, the error is not in                // the code right above (the for above will never execute)                // but in the init/steady schedule calculcation!                ASSERT(childrenExecs[nChild] == 0);            }            // have I done anything?            if (extraPhase.getNumPhases() != 0)            {                // yes - add the extra phase to the schedule!                utility.addSchedulePhase(extraPhase);            }        }    }