Parent-first and child-first execution

Whenever a state machine is in a composite or orthogonal state, multiple states are active at the same time: the composite/orthogonal state itself („parent”) and one or more of its substates („children”).

When an event occurs, the state machine checks the active states one by one for a transition that can be taken, subject to the event(s) received and the guard conditions on the transitions. As soon as a matching transition is found, it is taken immediately, and its target state becomes active. After executing the transition, the state machine does not check any further for other matching transitions.

Since the first match always wins, it is crucial in which order states are checked and how you can control that. In an orthogonal state, active substates are checked according to the arrangement of their regions: They are executed either from left to right or from top to bottom.

Whether the parent state or its child state(s) are checked first, you can specify by setting either the @ParentFirstExecution annotation or the @ChildFirstExecution annotation in the statechart’s definition section. If the definition section contains none of these annotations, @ParentFirstExecution is assumed. Whichever variant you choose, it is statechart-global and thus applies to all composite and orthogonal states.

Please note: Specifying parent-first or child-first execution pertains to checking for matching transitions only, not to entry and exit actions. Entry actions are always executed from the outside to the inside, i.e., on the parent state first and after that on the children. Exit actions are executed in reverse : in child states first, followed by the parent state.

Examples

Parent-first versus child-first execution are best explained by a couple of examples.

Simple child-first/parent-first examples

Example 1a:

Consider the statechart in the figure below. Composite state A and its substate B are active, and the @ChildFirstExecution annotation has been specified in the definition section.

Child-first, example 1a, before transition

Child-first, example 1a, before transition

When event e occurs, the state machine considers child state B first, finds a matching transition, and thus immediately proceeds to state D, see the figure below.

Child-first, example 1a, after transition

Child-first, example 1a, after transition

Example 1b:

Consider the statechart in the figure below. Composite state A and its substate B are active, and the @ParentFirstExecution annotation has been specified in the definition section.

Parent-first, example 1b, before transition

Parent-first, example 1b, before transition

When event e occurs, the state machine considers parent state A first, finds a matching transition, and thus immediately proceeds to state C, see the figure below.

Parent-first, example 1b, after transition

Parent-first, example 1b, after transition

Child-first/parent-first and reactions in states

The following examples are somewhat more complex. The statechart used in the examples defines the integer variables m, n, o, p, q, and r. Initially, they are all set to 0. Reactions in states A and B set these variables to non-zero values on certain conditions:

  • when entering a state,
  • when leaving a state, and
  • when receiving event e.

This is useful to understand which actions are performed (or not performed) and in which order.

The reactions in composite state A are as follows:

entry / m = 1
e / n = 1
exit / o = 1; r = 1

The reactions in substate B are as follows:

entry / m = 2
e / p = 1
exit / q = 1; r = 2

The settings above are the same for all subsequent examples, except for example 4.

Example 2a:

Consider the statechart in the figure below. Composite state A and its substate B are active, and the @ChildFirstExecution annotation has been specified in the definition section.

Child-first, example 2a, before transition

Child-first, example 2a, before transition

In this scenario, A and B have just been entered, and their entry actions have already been executed. Since the execution order of entry actions is independent of parent-first/child-first execution order and always proceeds from outer states to inner states, the entry action of A is executed first and sets variable m to 1. After that, the entry action of B is executed and overrides variable m with a value of 2.

When event e occurs, the state machine considers child state B first, finds a matching transition, and thus immediately proceeds to state D, see the figure below. The state machine executes the exit actions of A and B after these states have become inactive.

Child-first, example 2a, after transition

Child-first, example 2a, after transition

It is worth having a look at the variables and understand what has happened. When the state machine is in state D, the variable values are as follows:

Variable Value
m 2
n 0
o 1
p 0
q 1
r 1

We have already seen why m is 2.

Variable n would be set to 1 by a reaction in A, triggered by event e. However, since the statechart is in child-first mode, and the e event triggers an immediate transition from B to D, it is no surprise that n remains 0. The composite state is left before e / n = 1 in A gets any chance to be executed.

However, p is also 0, although B has priority over A, according to child-first execution. The reason is that an active state is checked for possible transitions first, and reactions within the state are executed second. This can lead to certain reactions not being executed at all. In this case, checking for possible transitions after receiving e finds the transition from B to D. This transition is executed immediately. „Immediately” means that B is left straight away. No further action will be done on it, and consequently the reaction e / p = 1 fails to be executed.

The only exception to the rule is are exit actions, because they are always executed when the corresponding state becomes inactive. That’s why the variables o, q, and r all have a value of 1: They have been modified in the exit actions of A and B. The execution of exit actions starts with the inner-most state and then proceeds to the outside. Here, the exit action of B has set q to 1 and r to 2. After that, the exit action of A has set o to 1 and has overridden r with 1.

Example 2b:

Consider the statechart in the figure below. Composite state A and its substate B are active, and the @ChildFirstExecution annotation has been specified in the definition section.

Parent-first, example 2b, before transition

Parent-first, example 2b, before transition

In this scenario, A and B have just been entered, and their entry actions have already been executed. Variable m has a value of 2, as explained in example 2a.

When event e occurs, the state machine considers parent state A first, finds a matching transition, and thus immediately proceeds to state C, see the figure below. The state machine executes the exit actions of A and B after these states have become inactive.

Parent-first, example 2b, after transition

Parent-first, example 2b, after transition

The variable values are the same as in example 2a and essentially for the same reasons: Entry and exit actions are executed in the same order, and any reactions on event e are not executed at all.

Example 3a:

Let’s make a small change now to the statechart in example 2a and add a guard condition [p == 1] to the transition B → D, see the figure below. Please note that the @ChildFirstExecution annotation has been specified in the definition section.

Child-first, example 3a, before transition

Child-first, example 3a, before transition

Event e causes the following to happen:

  1. Due to the @ChildFirstExecution annotation, state B is checked first for any transitions to be taken. However, since p is 0, the guard condition of B → D is not fulfilled, and the transition is not triggered.
  2. After that, the reactions of state B are considered. There is one reaction to an e event, and it sets variable p to 1. Now the guard condition would be fulfilled. However, looking for a matching transition has already been done and won’t be repeated in the current run-to-completion step.
  3. Since the child (state B) didn’t trigger a transition, checking continues with the parent (state A). Here a matching transition is found, and the execution flow proceeds to state C.
  4. The exit actions of B and A are executed.

The figure below shows the result.

Child-first, example 3a, after transition

Child-first, example 3a, after transition

The variables are set as follows:

Variable Value
m 2
n 0
o 1
p 1
q 1
r 1

Example 3b:

This example is here for the sake of completeness only. It is like example 3a, but with the @ParentFirstExecution annotation in effect.

The state machine reacts to an event e just like the one in example 2b: Since the parent is checked first and a matching transition from A to C is found, that transition is taken immediately, without considering B in any way, except for executing its exit action.

Thus in state C the variable values are as follows:

Variable Value
m 2
n 0
o 1
p 0
q 1
r 1

Example 4:

Last but not least, here’s an example that is left as an exercise to the reader: What is the next state in the statechart below after event e arrives? To find out whether your guess is correct, recreate the example and check it with the interactive statechart simulator.

Child-first, example 4, before transition

Child-first, example 4, before transition