}
    public void computeSchedule()    {        // compute the children's schedules and figure out        // how many times the split needs to be executed to feed        // all the buffers so the children can initialize (including the        // peek - pop amounts!)        int initSplitRunCount = 0;        {            // go through all the children and check how much            int nChild;            for (nChild = 0; nChild < getNumChildren(); nChild++)            {                // get the child                StreamInterface child = getHierarchicalChild(nChild);                ASSERT(child);                // compute child's schedule                child.computeSchedule();                // get the amount of data needed to initilize this child                int childInitDataConsumption = child.getInitPeek();                // this child may need more data in order to safely enter                // the steady state computation model (as per notes 02/07/02)                childInitDataConsumption                    += MAX(                        (child.getSteadyPeek() - child.getSteadyPop())                            - (child.getInitPeek() - child.getInitPop()),                        0);                // now figure out how many times the split needs to be run in                // initialization to accomodate this child                int splitRunCount;                if (childInitDataConsumption != 0)                {                    // just divide the amount of data needed by data received                    // per iteration of the split                    int splitDataSent = splitFlow.pushWeights[nChild];                    ASSERT(splitDataSent > 0);                    splitRunCount =                        (childInitDataConsumption + splitDataSent - 1)                            / splitDataSent;                }                else                {                    // the child doesn't need any data to intitialize, so I                    // don't need to run the split for it at all                    splitRunCount = 0;                }                // pick the max                if (splitRunCount > initSplitRunCount)                {                    initSplitRunCount = splitRunCount;                }            }        }        // compute the init schedule        {            PhasingSchedule initSched = new PhasingSchedule(this);            // run through the split an appropriate number of times            // and append it to the init schedule            {                PhasingSchedule splitSched = getSplitPhase();                int nRun;                for (nRun = 0; nRun < initSplitRunCount; nRun++)                {                    initSched.appendPhase(splitSched);                }            }            // now add the initialization schedules for all the children            {                int nChild;                for (nChild = 0; nChild < getNumChildren(); nChild++)                {                    StreamInterface child = getHierarchicalChild(nChild);                    int nStage = 0;                    for (; nStage < child.getNumInitStages(); nStage++)                    {                        initSched.appendPhase(                            child.getInitScheduleStage(nStage));                    }                }                addInitScheduleStage(initSched);            }        }        // compute the steady schedule        {            PhasingSchedule steadySched = new PhasingSchedule(this);            // first add the split schedule the right # of times            {                int nReps;                for (nReps = 0; nReps < getSplitNumRounds(); nReps++)                {                    steadySched.appendPhase(getSplitPhase());                }            }            // add the schedule for execution of all the children            // of the split join            {                int nChild;                for (nChild = 0; nChild < getNumChildren(); nChild++)                {                    StreamInterface child = getHierarchicalChild(nChild);                    int nRun;                    for (nRun = 0;                        nRun < childrenNumExecs[nChild].intValue();                        nRun++)                    {                        int nPhase;                        for (nPhase = 0;                            nPhase < child.getNumSteadyPhases();                            nPhase++)                        {                            steadySched.appendPhase(                                child.getSteadySchedulePhase(nPhase));                        }                    }                }            }            // finally add the join schedule the right # of times            {                int nReps;                for (nReps = 0; nReps < getJoinNumRounds(); nReps++)                {                    steadySched.appendPhase(getJoinPhase());                }            }            addSteadySchedulePhase(steadySched);        }    }