* @brief Users and applications can choose to have agents always * stop before a particular phase. If all agents have finished * finished running, this routine will check whether they * need to be stepped to a different phase. *********************************************************************/
| 465 | * need to be stepped to a different phase. |
| 466 | *********************************************************************/ |
| 467 | void RunScheduler::MoveTo_StopBeforePhase(bool forever, smlRunStepSize runStepSize) |
| 468 | { |
| 469 | // If we ran by decision_cycle and we've run the appropriate number of decisions, |
| 470 | // then step agent until it reached the correct phase where it should stop. |
| 471 | // Just before this point, (in scheduler while loop) we've checked and fired the |
| 472 | // OutputComplete and OutputGenerated events, so it should be fine to step |
| 473 | // an agent by phases until it gets to StopBefore, and then step the other |
| 474 | // agents in turn. |
| 475 | // |
| 476 | // If an interrupt was requested, it will be detected inside StepInClientThread |
| 477 | // and the appropriate events will be generated. The runResult will come back as |
| 478 | // INTERRUPTED, and the while loops will exit so that the run stops. |
| 479 | // |
| 480 | // Support for "Run 0" is somewhat complicated, since we might very well |
| 481 | // cross the I/O boundary. So we'll try stepping til OUTPUT done, then generate |
| 482 | // Update events, then step again til StopBeforePt is reached. Note: when we support |
| 483 | // StopBeforeUpdateWorld, we'll need to explicitly check for that before generating events. |
| 484 | |
| 485 | if ((runStepSize == sml_DECISION) || forever) |
| 486 | { |
| 487 | for (AgentMapIter iter = m_pKernelSML->m_AgentMap.begin() ; iter != m_pKernelSML->m_AgentMap.end() ; iter++) |
| 488 | { |
| 489 | AgentSML* pAgentSML = iter->second ; |
| 490 | if (pAgentSML->WasAgentOnRunList()) |
| 491 | { |
| 492 | AgentSML* pAgent = pAgentSML ; |
| 493 | smlPhase phase = pAgentSML->GetCurrentPhase() ; |
| 494 | smlRunResult runResult = pAgentSML->GetResultOfLastRun() ; |
| 495 | |
| 496 | // as in Bug 648, it's possible that a client has requested STOP_AFTER_DECISION |
| 497 | // while the agent was stopped at the m_StopBeforePhase, yet the agent run logic has |
| 498 | // dropped thru to this point without generating the interrupt yet. |
| 499 | if ((m_StopBeforePhase == phase) && (pAgent->GetRunState() == sml_RUNSTATE_STOPPED) && |
| 500 | (pAgent->GetInterruptFlags() & sml_STOP_AFTER_DECISION_CYCLE)) |
| 501 | { |
| 502 | pAgent->SetRunState(sml_RUNSTATE_INTERRUPTED); |
| 503 | runResult = pAgent->StepInClientThread(sml_PHASE) ; // force interrupt |
| 504 | } |
| 505 | |
| 506 | while ((phase != m_StopBeforePhase) && (sml_RUN_COMPLETED == runResult)) |
| 507 | { |
| 508 | runResult = pAgent->StepInClientThread(sml_PHASE) ; |
| 509 | phase = pAgentSML->GetCurrentPhase() ; |
| 510 | // don't cross Output-Input boundary here just to get to StopBefore phase for "Run 0" |
| 511 | if (sml_INPUT_PHASE == phase) |
| 512 | { |
| 513 | break; |
| 514 | } |
| 515 | } |
| 516 | pAgentSML->SetResultOfRun(runResult) ; |
| 517 | |
| 518 | // Notify listeners that this agent is finished running |
| 519 | /* pAgent->FireRunEndsEvent() ; */ // not if supporting run0 over O/I boundary |
| 520 | } |
| 521 | } |
| 522 | // If agents haven't reached the StopBeforePhase, then agents finished output |
| 523 | // and we need to possibly generate the UpdateWorld events before stepping any further. |
| 524 | // If not all agents finished output, then nothing will fire. |
nothing calls this directly
no test coverage detected