FSMActor ctrl = getController();
State currentState = ctrl.currentState();
ctrl.readInputs();
Transition transition;
// NOTE: If an enabled transition is already found,
// do not try to find another enabled transition.
// This guarantees that each firing of a modal model produces at most
// one discrete event.
// Also, the refinements are not fired to prevent the output from the
// enabled transitions being overwritten by the outputs from the
// refinements.
// This guarantees that only one event is produced at one discrete
// phase of execution.
if (_enabledTransition == null) {
///////////////////////////////////////////////////////////////////
// Handle preemptive transitions
// Only EXECUTE enabled transitions at the generating-event phase
// and iterating-purely-discrete-actors phase during a
// discrete-phase execution. In fact, if this director is used
// inside CT models only, we can further constraint the enabled
// transitions to be executed only in generating-event phase.
// However, to support the backwards compatibility such that
// HSFSMDirector can be also used inside DE models, we also allow the
// enabled transitions to be executed at the
// iterating-purely-discrete-actors phase.
// Check enabled transitions at the end of a continuous phase
// execution where the accuracy of the current step size is checked.
if ((getExecutionPhase() == CTExecutionPhase.GENERATING_EVENTS_PHASE)
|| (getExecutionPhase() == CTExecutionPhase.ITERATING_PURELY_DISCRETE_ACTORS_PHASE)) {
transition = ctrl.chooseTransition(currentState
.preemptiveTransitionList());
_transitionHasEvent = false;
} else {
transition = null;
}
// NOTE: The refinements of a transition can not and must not
// advance time. However, this requirement is not checked here.
if (transition != null) {
// record the enabled preemptive transition
// for the postfire() method.
_enabledTransition = transition;
// Disable mutation because we are in the middle of an
// iteration. The mutation will be enabled again in the
// postfire() method when the current phase of execution is
// updating continuous states.
_mutationEnabled = false;
Actor[] actors = transition.getRefinement();
if ((actors != null) && (actors.length > 0)) {
for (int i = 0; i < actors.length; ++i) {
if (_stopRequested) {
break;
}
if (actors[i].prefire()) {
actors[i].fire();
actors[i].postfire();
}
}
ctrl.readOutputsFromRefinement();
}
// An enabled preemptive transition preempts the
// firing of the enabled refienements.
return;
}
boolean visited = currentState.isVisited();
// Fire the refinements of the current state.
Iterator actors = _enabledRefinements.iterator();
while (actors.hasNext()) {
Actor actor = (Actor) actors.next();
if (_debugging && _verbose) {
_debug(getName(), " fire refinement", ((NamedObj) actor)
.getName());
}
// If this is the first time this state is visited, check
// whether the director for the refinement is a CT (Embedded)
// director. If so, establish the initial states for this
// refinement.
if (!visited) {
Director director = actor.getDirector();
if (director instanceof CTEmbeddedDirector) {
((CTEmbeddedDirector) director)
.setInitialStatesNotReady();
}
}
actor.fire();
}
// The controller needs to know the most updated outputs from
// the firing of the enabled refinements.
ctrl.readOutputsFromRefinement();
if (!visited) {
currentState.setVisited(true);
}
//////////////////////////////////////////////////////////////////
// Handle nonpreemptive transitions
// Only EXECUTE enabled transitions at the generating-event phase
// and iterating-purely-discrete-actors phase during a
// discrete-phase execution. In fact, if this director is used
// inside CT models only, we can further constraint the enabled
// transitions to be executed only in generating-event phase.
// However, to support the backwards
// compatibility such that HSFSMDirector can be also used inside DE
// models, we also allow the enabled transitions to be executed at
// the iterating-purely-discrete-actors phase.
// Check enabled transitions at the end of a continuous
// phase of execution to verify the accuracy of current step size.
if ((getExecutionPhase() == CTExecutionPhase.GENERATING_EVENTS_PHASE)
|| (getExecutionPhase() == CTExecutionPhase.ITERATING_PURELY_DISCRETE_ACTORS_PHASE)) {
// Note that the output actions associated with the transition
// are executed.
transition = ctrl.chooseTransition(currentState
.nonpreemptiveTransitionList());
_transitionHasEvent = false;
} else {
transition = null;
}
// execute the refinements of the enabled transition.
if (transition != null) {
// record the enabled nonpreemptive transition for
// the postfire() method
_enabledTransition = transition;
// Disable mutation because we are in the middle of an
// iteration. The mutation will be enabled again in the
// postfire() method when the current phase of execution is
// updating continuous states.
_mutationEnabled = false;
Actor[] transitionActors = transition.getRefinement();
if ((transitionActors != null) && (transitionActors.length > 0)) {
for (int i = 0; i < transitionActors.length; ++i) {
if (_stopRequested) {
break;