Skip to content

History and deferred transitions

Coming back to a superstate where you left it with history and shallow history, and arriving quietly with deferred transitions.

Your phone is playing the second track of an album when a call comes in. After the call you expect the music to carry on with track 2, not to start the album again. A transition into a superstate normally does start it again, from its initial states. A history transition brings it back to where it was when it was left.

The second half of this chapter is about a different modifier for transitions into a state, deferred, which makes the arrival quiet: the target state does nothing in the tick it is entered.

Both players below leave Playing for OnCall when call is pressed, and go back when hangUp is pressed. The only difference is the last line: PlayerRestart goes back with go to Playing, PlayerHistory with go to Playing history.

PlayerRestart and PlayerHistoryComparison

Diagrams

PlayerRestart

Diagram of PlayerRestartStates: Playing (initial, superstate), Track1 (initial, superstate), Track2 (superstate), Track3 (superstate), OnCall (superstate). Transitions: Track1 to Track2: next; Track2 to Track3: next; Track3 to Track1: next; Playing to OnCall: call; OnCall to Playing: hangUp.PlayerRestartinput boolnext, call, hangUpoutput inttrack = 0PlayingTrack1entry/ track = 1Track2entry/ track = 2Track3entry/ track = 3nextnextnextOnCallentry/ track = 0callhangUp

PlayerHistory

Diagram of PlayerHistoryStates: Playing (initial, superstate), Track1 (initial, superstate), Track2 (superstate), Track3 (superstate), OnCall (superstate). Transitions: Track1 to Track2: next; Track2 to Track3: next; Track3 to Track1: next; Playing to OnCall: call; OnCall to Playing: hangUp.PlayerHistoryinput boolnext, call, hangUpoutput inttrack = 0PlayingTrack1entry/ track = 1Track2entry/ track = 2Track3entry/ track = 3nextnextnextOnCallentry/ track = 0callhangUp

Code

PlayerRestart

scchart PlayerRestart {
input bool next, call, hangUp
output int track = 0
initial state Playing {
initial state Track1 {
entry do track = 1
}
if next go to Track2
state Track2 {
entry do track = 2
}
if next go to Track3
state Track3 {
entry do track = 3
}
if next go to Track1
}
if call go to OnCall
state OnCall {
entry do track = 0
}
if hangUp go to Playing
}

PlayerHistory

scchart PlayerHistory {
input bool next, call, hangUp
output int track = 0
initial state Playing {
initial state Track1 {
entry do track = 1
}
if next go to Track2
state Track2 {
entry do track = 2
}
if next go to Track3
state Track3 {
entry do track = 3
}
if next go to Track1
}
if call go to OnCall
state OnCall {
entry do track = 0
}
if hangUp go to Playing history
}
Tick 0 of 9
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it.
Timing diagram of PlayerRestart and PlayerHistory, no ticks yet
Tickinput bool nextinput bool callinput bool hangUpPlayerRestart: output int trackPlayerRestart: Active state of the chartPlayerRestart: Active state of the region of PlayingPlayerHistory: output int trackPlayerHistory: Active state of the chartPlayerHistory: Active state of the region of Playing
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 9 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 9 ticks, the same inputs for both charts:

  1. next = false, call = false, hangUp = falseTick 1 enters Playing and Track1 in both players (track = 1).
  2. next = trueTrack1 to Track2 (track = 2).
  3. next = falseListening to track 2.
  4. call = trueA call comes in: both players leave Playing for OnCall (track = 0). PlayerHistory remembers that Playing was in Track2.
  5. call = false, hangUp = trueHang up. PlayerRestart: go to Playing enters Playing afresh, in its initial state Track1 (track = 1). PlayerHistory: go to Playing history resumes Track2, and since Track2 is entered again, its entry action runs (track = 2).
  6. hangUp = falsePlayerRestart has lost its place; PlayerHistory carries on with track 2.
  7. next = true, call = truenext and call in the same tick. go to OnCall is a weak abort, so the inside of Playing first takes its last step: Track1 to Track2 in PlayerRestart, Track2 to Track3 in PlayerHistory. Then both go to OnCall (track = 0).
  8. next = false, call = false, hangUp = trueHang up. PlayerRestart starts at track 1 again. PlayerHistory resumes the state entered last, Track3, the one reached in the abort tick (track = 3).
  9. hangUp = falseTrack 1 in PlayerRestart, track 3 in PlayerHistory.
The tour skips to track 2, takes a call in tick 4 and hangs up in tick 5: PlayerRestart is back on track 1, PlayerHistory on track 2.

The value of track after each tick of the tour:

Tick Inputs Restart History
1 none 1 1
2 next 2 2
3 none 2 2
4 call 0 0
5 hangUp 1 2
6 none 1 2
7 next and call 0 0
8 hangUp 1 3
9 none 1 3

In the diagram a history transition ends in a small dark circle with an H in it, next to the arrowhead (here H*, for reasons explained below).

go to S history enters S in the states that were active in each of its regions when S was last left, at every level of nesting. The first time S is entered this way, there is nothing to remember, and it starts from its initial states as usual.

Three details matter in practice:

  • The resumed states are entered again. Their entry actions run, and their immediate transitions are checked, just as for any other entry. In tick 5, Track2’s entry action sets track back to 2.
  • History remembers the state that was entered last. In tick 7, next and call arrive together. go to OnCall is a weak abort, so the inside of Playing first takes its last step, from Track2 to Track3 (see Aborts). That step counts: in tick 8, history resumes Track3. The one exception is a state entered with deferred, which history does not record at all (below).
  • History belongs to the transition, not to the state. Every other transition into S still starts it from its initial states. You can say so explicitly with go to S reset, which is the same as writing nothing.

History brings back where you were, but not what your variables held. Here Playing counts the seconds of the current track in a local variable, seconds, and copies it to the output shown. A call comes in during tick 4, and the player is resumed with history in tick 5. What does shown say in tick 6? Predict, check, then open the explanation.

ResumeLocalsPrediction

Diagram

Diagram of ResumeLocalsStates: Playing (initial, superstate), Track (initial), OnCall. Transitions: Track to Track: true / seconds++; shown = seconds; Playing to OnCall: call; OnCall to Playing: hangUp.ResumeLocalsinput boolcall, hangUpoutput intshown = 0Playingintseconds = 0Tracktrue/ seconds++;shown = secondsOnCallcallhangUp

Code

scchart ResumeLocals {
input bool call, hangUp
output int shown = 0
initial state Playing {
int seconds = 0
initial state Track
if true do seconds++; shown = seconds go to Track
}
if call go to OnCall
state OnCall
if hangUp go to Playing history
}

seconds is declared inside Playing. Does history bring back its value?

Inputs per tick. A value in grey was not set in that tick: it holds from an earlier one.

TickcallhangUp
1falsefalse
2falsefalse
3falsefalse
4truefalse
5falsetrue
6falsefalse
Plays the scenario on the diagram, then marks each answer.
Explanation

shown is 1. Resuming with history is still an entry of Playing, and a state’s local variables are initialised every time the state is entered (see Superstates). So seconds starts again from 0 while Track is resumed. The same goes for the locals of the resumed inner states, and for their entry actions, which run again.

If a value must survive the visit, declare it outside the superstate, or mark it static:

initial state Playing {
static int seconds = 0

A static local is initialised once, when the chart starts, and keeps its value when its state is left and entered again, like a static local variable in C. With that one word, the player above carries on counting after the call: shown is 4 in tick 6.

history on its own is deep: it restores every level of nesting. shallow history restores only the states directly inside the target; any superstate among them starts from its own initial states.

The menu below has a Settings superstate with two pages, Display and Sound, each a superstate with two screens. The screen shown is a number in screen: 11 and 12 for the two display screens, 21 and 22 for the two sound screens, 0 for Home.

MenuDeep and MenuShallowComparison

Diagrams

MenuDeep

Diagram of MenuDeepStates: Home (initial, superstate), Settings (superstate), Display (initial, superstate), Brightness (initial, superstate), Contrast (superstate), Sound (superstate), Volume (initial, superstate), Balance (superstate). Transitions: Brightness to Contrast: right; Volume to Balance: right; Display to Sound: down; Home to Settings: menu; Settings to Home: home.MenuDeepinput boolmenu, home, down, rightoutput intscreen = 0Homeentry/ screen = 0SettingsDisplayBrightnessentry/ screen = 11Contrastentry/ screen = 12rightSoundVolumeentry/ screen = 21Balanceentry/ screen = 22rightdownmenuhome

MenuShallow

Diagram of MenuShallowStates: Home (initial, superstate), Settings (superstate), Display (initial, superstate), Brightness (initial, superstate), Contrast (superstate), Sound (superstate), Volume (initial, superstate), Balance (superstate). Transitions: Brightness to Contrast: right; Volume to Balance: right; Display to Sound: down; Home to Settings: menu; Settings to Home: home.MenuShallowinput boolmenu, home, down, rightoutput intscreen = 0Homeentry/ screen = 0SettingsDisplayBrightnessentry/ screen = 11Contrastentry/ screen = 12rightSoundVolumeentry/ screen = 21Balanceentry/ screen = 22rightdownmenuhome

Code

MenuDeep

@layout[elk.direction] DOWN
scchart MenuDeep {
input bool menu, home, down, right
output int screen = 0
initial state Home {
entry do screen = 0
}
if menu go to Settings history
state Settings {
initial state Display {
initial state Brightness {
entry do screen = 11
}
if right go to Contrast
state Contrast {
entry do screen = 12
}
}
if down go to Sound
state Sound {
initial state Volume {
entry do screen = 21
}
if right go to Balance
state Balance {
entry do screen = 22
}
}
}
if home go to Home
}

MenuShallow

@layout[elk.direction] DOWN
scchart MenuShallow {
input bool menu, home, down, right
output int screen = 0
initial state Home {
entry do screen = 0
}
if menu go to Settings shallow history
state Settings {
initial state Display {
initial state Brightness {
entry do screen = 11
}
if right go to Contrast
state Contrast {
entry do screen = 12
}
}
if down go to Sound
state Sound {
initial state Volume {
entry do screen = 21
}
if right go to Balance
state Balance {
entry do screen = 22
}
}
}
if home go to Home
}
Tick 0 of 10
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it.
Timing diagram of MenuDeep and MenuShallow, no ticks yet
Tickinput bool menuinput bool homeinput bool downinput bool rightMenuDeep: output int screenMenuDeep: Active state of the chartMenuDeep: Active state of the region of SettingsMenuDeep: Active state of the region of Settings.DisplayMenuDeep: Active state of the region of Settings.SoundMenuShallow: output int screenMenuShallow: Active state of the chartMenuShallow: Active state of the region of SettingsMenuShallow: Active state of the region of Settings.DisplayMenuShallow: Active state of the region of Settings.Sound
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 10 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 10 ticks, the same inputs for both charts:

  1. menu = false, home = false, down = false, right = falseTick 1 enters Home in both menus (screen = 0).
  2. menu = trueThe first visit to Settings: there is nothing to remember yet, so both start in Display and Brightness (screen = 11).
  3. menu = false, right = trueBrightness to Contrast (12).
  4. right = false, home = trueBack Home (0). Both charts remember where Settings was.
  5. home = false, menu = trueBack to Settings with history. MenuDeep: history is deep, so Settings resumes in Display, and Display resumes in Contrast (12). MenuShallow: shallow history restores only the level directly inside Settings, so Display is resumed but starts again in Brightness (11).
  6. menu = false, down = trueDisplay to Sound, which starts in Volume (21) in both.
  7. down = false, right = trueVolume to Balance (22).
  8. right = false, home = trueHome (0).
  9. home = false, menu = trueDeep history resumes Sound and, inside it, Balance (22). Shallow history resumes Sound, starting in Volume (21).
  10. menu = falseMenuDeep is on the Balance screen, MenuShallow on Volume.
The tour opens Contrast in tick 3, goes home and opens the menu again in tick 5: deep history shows Contrast (12), shallow history Brightness (11).

The value of screen after each tick, from tick 2:

Tick Inputs Deep Shallow
2 menu 11 11
3 right 12 12
4 home 0 0
5 menu 12 11
6 down 21 21
7 right 22 22
8 home 0 0
9 menu 22 21
10 none 22 21

Both kinds remember which page was open. Only deep history also remembers the screen within the page. In the diagram, deep history is drawn as H*, shallow history as H.

A history transition that is silently ignored

Section titled “A history transition that is silently ignored”

Now put the menu inside a device that can be switched off. Home and Settings move into a superstate On, next to an Off state:

MenuNested and MenuNestedFixedComparison

Diagrams

MenuNested

Diagram of MenuNestedStates: Off (initial, superstate), On (superstate), Home (initial, superstate), Settings (superstate), Brightness (initial, superstate), Contrast (superstate). Transitions: Brightness to Contrast: right; Home to Settings: menu; Settings to Home: home; Off to On: power; On to Off: !power.MenuNestedinput boolpower, menu, home, rightoutput intscreen = 0Offentry/ screen = -1OnHomeentry/ screen = 0SettingsBrightnessentry/ screen = 11Contrastentry/ screen = 12rightmenuhomepower!power

MenuNestedFixed

Diagram of MenuNestedFixedStates: Off (initial, superstate), On (superstate), Home (initial, superstate), Settings (superstate), Brightness (initial, superstate), Contrast (superstate). Transitions: Brightness to Contrast: right; Home to Settings: menu; Settings to Home: home; Off to On: power; On to Off: !power.MenuNestedFixedinput boolpower, menu, home, rightoutput intscreen = 0Offentry/ screen = -1OnHomeentry/ screen = 0SettingsBrightnessentry/ screen = 11Contrastentry/ screen = 12rightmenuhomepower!power

Code

MenuNested

@layout[elk.direction] DOWN
scchart MenuNested {
input bool power, menu, home, right
output int screen = 0
initial state Off {
entry do screen = -1
}
if power go to On
state On {
initial state Home {
entry do screen = 0
}
if menu go to Settings history
state Settings {
initial state Brightness {
entry do screen = 11
}
if right go to Contrast
state Contrast {
entry do screen = 12
}
}
if home go to Home
}
if !power go to Off
}

MenuNestedFixed

@layout[elk.direction] DOWN
scchart MenuNestedFixed {
input bool power, menu, home, right
output int screen = 0
initial state Off {
entry do screen = -1
}
if power go to On shallow history
state On {
initial state Home {
entry do screen = 0
}
if menu go to Settings history
state Settings {
initial state Brightness {
entry do screen = 11
}
if right go to Contrast
state Contrast {
entry do screen = 12
}
}
if home go to Home
}
if !power go to Off
}
Tick 0 of 9
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it.
Timing diagram of MenuNested and MenuNestedFixed, no ticks yet
Tickinput bool powerinput bool menuinput bool homeinput bool rightMenuNested: output int screenMenuNested: Active state of the chartMenuNested: Active state of the region of OnMenuNested: Active state of the region of On.SettingsMenuNestedFixed: output int screenMenuNestedFixed: Active state of the chartMenuNestedFixed: Active state of the region of OnMenuNestedFixed: Active state of the region of On.Settings
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 9 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 9 ticks, the same inputs for both charts:

  1. power = false, menu = false, home = false, right = falseTick 1 enters Off in both (screen = −1).
  2. power = truePower on: the first visit to On starts in Home (0).
  3. menu = trueThe first visit to Settings: Brightness (11).
  4. menu = false, right = trueContrast (12).
  5. right = false, home = trueHome (0).
  6. home = false, menu = trueBack to Settings with history. MenuNested: surprise, Settings starts again in Brightness (11). On is not the target of a history transition, so KIELER silently treats go to Settings history as a plain go to Settings. MenuNestedFixed: On is a history target (from Off), so the history inside it works: Contrast (12).
  7. menu = false, power = falsePower off: Off (−1).
  8. power = truePower on. MenuNested starts On in Home (0). MenuNestedFixed enters On with shallow history, so it resumes in Settings, which starts again in Brightness (11). The fix changed what switching on does.
  9. Home in MenuNested, Brightness in MenuNestedFixed.
Note: KIELER ignores this history: Settings restarts from its initial state (MenuNested)
  • Note in MenuNested, line 15, column 5KIELER only handles history on transitions into states of the chart's top-level regions, or inside a state that is itself the target of a history transition. Here Settings is nested in a state without one, so this transition behaves like a normal transition. Move the mode switch to the top level, or give the enclosing state a history transition too.
The tour opens Contrast in tick 4, goes home and opens the menu again in tick 6: MenuNested forgets, MenuNestedFixed remembers.

In MenuNested the history transition if menu go to Settings history has no effect at all: in tick 6 Settings starts again in Brightness. KIELER gives no error and no warning. (The note under the comparison is this guide’s: it marks KIELER quirks that KIELER itself does not mention.)

The reason is a limitation of KIELER’s compiler. It only processes history transitions into states of the chart’s top-level regions, and, inside them, history transitions into states nested in a state that is itself the target of a history transition. Any other history transition is quietly treated as a plain go to. Settings is nested inside On, and On is only ever entered with a plain go to On, so the history on Settings is dropped.

MenuNestedFixed makes On a history target: Off goes back with go to On shallow history. Now the history inside On works (tick 6 shows Contrast again). But the fix also changes what switching on does: in tick 8 the device comes back on the Settings page instead of Home. When that is not what you want, restructure the chart so that the state you return to with history sits in a top-level region.

A transition into a state can also be marked deferred: go to S deferred. A deferred entry is a quiet one. In the tick it happens, S does none of its immediate behaviour:

  • its entry actions do not run, and they never will for this visit;
  • its immediate during actions and its immediate outgoing transitions wait until the next tick.

From the next tick on, S behaves as if it had been entered normally one tick earlier: its delayed transitions and during actions can already run, and so can the immediate behaviour that waited.

In this chart, entering Hall rings a chime (an entry action) and walks straight on into Room (an immediate transition). The transition into Hall is deferred:

ArriveDeferredSimulation

Diagram

Diagram of ArriveDeferredStates: Outside (initial), Hall (superstate), Room. Transitions: Outside to Hall: walk; Hall to Room: / steps++.ArriveDeferredinput boolwalkoutput intchimes = 0, steps = 0OutsideHallentry/ chimes++Roomwalk/ steps++

Code

scchart ArriveDeferred {
input bool walk
output int chimes = 0, steps = 0
initial state Outside
if walk go to Hall deferred
state Hall {
entry do chimes++
}
immediate do steps++ go to Room
state Room
}
Tick 0 of 4
Inputs for tick 1 Boolean input: true while on. It keeps its value until you change it.
Timing diagram of ArriveDeferred
Tickinput bool walkoutput int chimesoutput int stepsActive state of the chart
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 4 ticks Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 4 ticks:

  1. walk = falseTick 1 enters Outside.
  2. walk = truego to Hall deferred: Hall is entered quietly. No chime, and its immediate transition waits.
  3. walk = falseOne tick later the immediate transition fires (steps = 1). The entry action never runs for this visit (chimes stays 0).
  4. In Room.
Tick 2 arrives in Hall quietly; the immediate transition fires in tick 3; the chime never rings.

chimes and steps after each tick, with a normal go to Hall and with go to Hall deferred:

Tick walk Normal Deferred
1 false 0, 0 0, 0
2 true 1, 1 0, 0
3 false 1, 1 0, 1

In the diagram, a deferred transition has a small red circle next to its arrowhead.

deferred is for coming back to a state whose immediate transitions should not fire again in the very tick you arrive, because the inputs of that tick still describe the job that has just finished. This coffee machine starts filling as soon as a cup stands under the spout, immediate if cup do fills++ go to Filling, and goes back to Ready when the cup is full. The inputs of a tick are read at its start, so in the tick of full the full cup is still there:

FillerNormal and FillerDeferredComparison

Diagrams

FillerNormal

Diagram of FillerNormalStates: Ready (initial), Filling. Transitions: Ready to Filling: cup / fills++; Filling to Ready: full.FillerNormalinput boolcup, fulloutput intfills = 0ReadyFillingcup/ fills++full

FillerDeferred

Diagram of FillerDeferredStates: Ready (initial), Filling. Transitions: Ready to Filling: cup / fills++; Filling to Ready: full.FillerDeferredinput boolcup, fulloutput intfills = 0ReadyFillingcup/ fills++full

Code

FillerNormal

scchart FillerNormal {
input bool cup, full
output int fills = 0
initial state Ready
immediate if cup do fills++ go to Filling
state Filling
if full go to Ready
}

FillerDeferred

scchart FillerDeferred {
input bool cup, full
output int fills = 0
initial state Ready
immediate if cup do fills++ go to Filling
state Filling
if full go to Ready deferred
}
Tick 0 of 7
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it.
Timing diagram of FillerNormal and FillerDeferred, no ticks yet
Tickinput bool cupinput bool fullFillerNormal: output int fillsFillerNormal: Active state of the chartFillerDeferred: output int fillsFillerDeferred: Active state of the chart
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 7 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 7 ticks, the same inputs for both charts:

  1. cup = true, full = falseA cup stands under the spout in tick 1. Ready’s transition is immediate, so both machines start filling it at once (fills = 1). The initial entry is never deferred.
  2. Both are Filling.
  3. full = trueThe cup is full. Nobody has taken it away yet, so cup is still true in this tick. FillerNormal: go to Ready enters Ready, whose immediate transition sees cup and starts filling the full cup again (2). FillerDeferred: go to Ready deferred arrives in Ready quietly, so its immediate transition waits (1).
  4. full = false, cup = falseThe cup has been taken away. FillerDeferred’s Ready now looks at cup, finds no cup, and waits. FillerNormal is Filling with nothing under the spout.
  5. cup = trueA new cup. FillerDeferred starts filling it (2). FillerNormal is still in Filling and counts nothing.
  6. full = trueThe second cup is full and still there. FillerNormal starts on it again (3); FillerDeferred waits a tick (2).
  7. full = false, cup = falseThe cup is gone. Two cups: FillerDeferred counted two fills, FillerNormal three.
Each full cup is still under the spout in the tick it is full (ticks 3 and 6): FillerNormal starts filling it again at once, FillerDeferred waits a tick and finds it gone.

With a plain go to Ready, Ready’s immediate transition reads cup in the same tick and starts on the full cup again: two cups, three fills. With go to Ready deferred, Ready arrives quietly and first looks at cup in the next tick, when the cup has been taken. The initial entry in tick 1 is never deferred: both machines start on the first cup at once.

deferred buys exactly one tick. If a cup may stay under the spout for longer, wait until it has gone instead, with a state between Filling and Ready that is left if !cup.

For a superstate, deferred always skips the superstate’s own immediate behaviour: its entry actions, its immediate during actions and its immediate outgoing transitions. Whether its inside starts a tick late as well depends, surprisingly, on the superstate’s other incoming transitions. The rule of thumb: a deferred entry into a superstate may start its inside one tick late, so check the timing in the simulator.

The two charts below are identical except that DeferredMixed has a second, normal transition into Inside, which is never even taken:

DeferredOnly and DeferredMixedComparison

Diagrams

DeferredOnly

Diagram of DeferredOnlyStates: Outside (initial), Inside (superstate), First (initial, superstate), Second. Transitions: First to Second: true / step++; Outside to Inside: walk.DeferredOnlyinput boolwalkoutput intouterEntry = 0, innerEntry = 0, step = 0OutsideInsideentry/ outerEntry++Firstentry/ innerEntry++Secondtrue/ step++walk

DeferredMixed

Diagram of DeferredMixedStates: Outside (initial), Inside (superstate), First (initial, superstate), Second. Transitions: First to Second: true / step++; Outside to Inside: 1: walk; Outside to Inside: 2: rush.DeferredMixedinput boolwalk, rushoutput intouterEntry = 0, innerEntry = 0, step = 0OutsideInsideentry/ outerEntry++Firstentry/ innerEntry++Secondtrue/ step++1: walk2: rush

Code

DeferredOnly

scchart DeferredOnly {
input bool walk
output int outerEntry = 0, innerEntry = 0, step = 0
initial state Outside
if walk go to Inside deferred
state Inside {
entry do outerEntry++
initial state First {
entry do innerEntry++
}
if true do step++ go to Second
state Second
}
}

DeferredMixed

scchart DeferredMixed {
input bool walk, rush
output int outerEntry = 0, innerEntry = 0, step = 0
initial state Outside
if walk go to Inside deferred
if rush go to Inside
state Inside {
entry do outerEntry++
initial state First {
entry do innerEntry++
}
if true do step++ go to Second
state Second
}
}
Tick 0 of 5
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it.
Timing diagram of DeferredOnly and DeferredMixed, no ticks yet
Tickinput bool walkinput bool rushDeferredOnly: output int outerEntryDeferredOnly: output int innerEntryDeferredOnly: output int stepDeferredOnly: Active state of the chartDeferredOnly: Active state of the region of InsideDeferredMixed: output int outerEntryDeferredMixed: output int innerEntryDeferredMixed: output int stepDeferredMixed: Active state of the chartDeferredMixed: Active state of the region of Inside
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 5 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 5 ticks, the same inputs for both charts:

  1. walk = false, rush = falseTick 1 enters Outside. rush stays false throughout: DeferredMixed’s normal transition into Inside is never taken, but it is there.
  2. walk = trueThe deferred entry into Inside. DeferredOnly: every transition into Inside is deferred, so KIELER postpones the whole entry by a tick, and nothing inside happens yet (innerEntry = 0). DeferredMixed: Inside is entered now; only its own entry action is skipped, and First’s entry action runs (innerEntry = 1).
  3. walk = falseDeferredOnly really enters Inside now: First’s entry action runs (innerEntry = 1). In DeferredMixed, First’s delayed transition fires at the normal time (step = 1).
  4. DeferredOnly’s First fires one tick later than after a normal entry (step = 1). Inside’s own entry action has run in neither chart (outerEntry = 0).
  5. Both in Second.
Note: KIELER enters Inside one tick late here: its inner states start in the tick after the deferred transition, so everything inside Inside happens a tick later than after a normal entry (DeferredOnly)
  • Note in DeferredOnly, line 6, column 5Because every transition into Inside is deferred, KIELER replaces the entry by an extra state and a delayed transition. If Inside also had a normal incoming transition, its inner states would start in the deferred tick itself.
The same deferred entry in tick 2: the inside of Inside starts a tick late in DeferredOnly, on time in DeferredMixed.
The exact rule

KIELER picks one of two implementations of deferred for a superstate:

  • If every transition into the superstate is deferred, all in the same way, and the superstate cannot get back to itself through immediate transitions, KIELER really enters it one tick later. In the deferred tick nothing inside happens; in the next tick the inner initial states are entered (their entry actions run) and the inside starts, so its delayed transitions fire one tick later than after a normal entry. That is DeferredOnly.
  • Otherwise the superstate is entered in the deferred tick: the entry actions of its inner initial states run, and the inside keeps its normal timing. That is DeferredMixed.

deferred can also be combined with history (go to M deep deferred history). KIELER then resumes M one tick late: in the deferred tick nothing happens, and in the next tick the remembered inner state is entered and its entry action runs, while M’s own entry action does not.

go to B deep deferred extends the quiet arrival to the inner initial states, all the way down: their entry actions never run for this visit, and their immediate transitions wait a tick. The two charts below differ only in the word deep:

HouseDeferred and HouseDeepComparison

Diagrams

HouseDeferred

Diagram of HouseDeferredStates: Outside (initial), House (superstate), Hall (initial, superstate), Room. Transitions: Hall to Room: / steps++; Outside to House: walk.HouseDeferredinput boolwalkoutput intchimes = 0, lights = 0, steps = 0OutsideHouseentry/ chimes++Hallentry/ lights++Room/ steps++walk

HouseDeep

Diagram of HouseDeepStates: Outside (initial), House (superstate), Hall (initial, superstate), Room. Transitions: Hall to Room: / steps++; Outside to House: walk.HouseDeepinput boolwalkoutput intchimes = 0, lights = 0, steps = 0OutsideHouseentry/ chimes++Hallentry/ lights++Room/ steps++walk

Code

HouseDeferred

scchart HouseDeferred {
input bool walk
output int chimes = 0, lights = 0, steps = 0
initial state Outside
if walk go to House deferred
state House {
entry do chimes++
initial state Hall {
entry do lights++
}
immediate do steps++ go to Room
state Room
}
}

HouseDeep

scchart HouseDeep {
input bool walk
output int chimes = 0, lights = 0, steps = 0
initial state Outside
if walk go to House deep deferred
state House {
entry do chimes++
initial state Hall {
entry do lights++
}
immediate do steps++ go to Room
state Room
}
}
Tick 0 of 4
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it.
Timing diagram of HouseDeferred and HouseDeep, no ticks yet
Tickinput bool walkHouseDeferred: output int chimesHouseDeferred: output int lightsHouseDeferred: output int stepsHouseDeferred: Active state of the chartHouseDeferred: Active state of the region of HouseHouseDeep: output int chimesHouseDeep: output int lightsHouseDeep: output int stepsHouseDeep: Active state of the chartHouseDeep: Active state of the region of House
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 4 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 4 ticks, the same inputs for both charts:

  1. walk = falseTick 1 enters Outside in both charts.
  2. walk = trueBoth enter House deferred. Every transition into House is deferred, so KIELER really enters it a tick later: in this tick nothing of House happens in either chart.
  3. walk = falseThe inside starts. HouseDeferred: the inner initial state Hall is entered normally, so its entry action runs (lights = 1) and its immediate transition fires (steps = 1). HouseDeep: deep deferred extends the quiet arrival to Hall, so its entry action is skipped (lights = 0); only its immediate transition runs (steps = 1). Neither chart runs House’s own entry action (chimes = 0).
  4. Both in Room. The entry actions that were skipped never run for this visit.
Note: KIELER enters House one tick late here: its inner states start in the tick after the deferred transition, so everything inside House happens a tick later than after a normal entry (HouseDeferred and HouseDeep)
  • Note in HouseDeferred, line 6, column 5Because every transition into House is deferred, KIELER replaces the entry by an extra state and a delayed transition. If House also had a normal incoming transition, its inner states would start in the deferred tick itself.
  • Note in HouseDeep, line 6, column 5Because every transition into House is deep deferred, KIELER replaces the entry by an extra state and a delayed transition. If House also had a normal incoming transition, its inner states would start in the deferred tick itself.
The inside of House starts in tick 3. Hall’s entry action switches on a light in HouseDeferred (lights = 1) but not in HouseDeep; neither chart runs House’s own entry action.

Every transition into House is deferred, so in both charts the inside starts a tick late (the first case of the exact rule above). deep decides only whether the inner initial state Hall arrives quietly as well.

KIELER keeps the history of a superstate with an entry action that it adds to every state inside: each entry records the state. A deferred entry skips the entry actions, and that one with them. So history does not remember a state entered with deferred; it resumes the state that was recorded before it:

RoomsHistorySimulation

Diagram

Diagram of RoomsHistoryStates: House (initial, superstate), Hall (initial, superstate), Kitchen, Garden. Transitions: Hall to Kitchen: walk / room = 2; House to Garden: out / room = 9; Garden to House: back.RoomsHistoryinput boolwalk, out, backoutput introom = 0HouseHallentry/ room = 1Kitchenwalk/ room = 2Gardenout/ room = 9back

Code

scchart RoomsHistory {
input bool walk, out, back
output int room = 0
initial state House {
initial state Hall {
entry do room = 1
}
if walk do room = 2 go to Kitchen deferred
state Kitchen
}
if out do room = 9 go to Garden
state Garden
if back go to House history
}
Tick 0 of 6
Inputs for tick 1 Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it.
Timing diagram of RoomsHistory
Tickinput bool walkinput bool outinput bool backoutput int roomActive state of the chartActive state of the region of House
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 6 ticks Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 6 ticks:

  1. walk = false, out = false, back = falseTick 1 enters House and Hall; Hall’s entry action sets room = 1.
  2. walk = truego to Kitchen deferred: the transition’s own effect sets room = 2, and Kitchen is entered quietly.
  3. walk = falseIn Kitchen.
  4. out = trueOut into the Garden (room = 9). House was in Kitchen when it was left.
  5. out = false, back = truego to House history resumes Hall, not Kitchen: Kitchen was entered with deferred, so KIELER never recorded it. Hall’s entry action runs again (room = 1).
  6. back = falseIn Hall.
Kitchen is entered with deferred in tick 2. After the garden, go to House history in tick 5 resumes Hall, not Kitchen.

KIELER gives no warning. If history must come back to a state, enter that state without deferred.

Wake up on the right page

Kiosk shows news and weather pages; open shows the details of a page, and idle switches to a screensaver. At the moment a touch on the screensaver always goes back to the news headlines. Change the chart so that a touch goes back to the page that was showing before the screensaver (news or weather), but always to that page’s first screen (11 or 21), never to the details.

Show the starter chart
scchart Kiosk {
input bool idle, touch, next, open
output int screen = 11
initial state Pages {
initial state News {
initial state Headlines {
entry do screen = 11
}
if open go to Story
state Story {
entry do screen = 12
}
}
if next go to Weather
state Weather {
initial state Today {
entry do screen = 21
}
if open go to Week
state Week {
entry do screen = 22
}
}
}
if idle go to Screensaver
state Screensaver {
entry do screen = 0
}
if touch go to Pages
}
Show a solution
scchart Kiosk {
input bool idle, touch, next, open
output int screen = 11
initial state Pages {
initial state News {
initial state Headlines {
entry do screen = 11
}
if open go to Story
state Story {
entry do screen = 12
}
}
if next go to Weather
state Weather {
initial state Today {
entry do screen = 21
}
if open go to Week
state Week {
entry do screen = 22
}
}
}
if idle go to Screensaver
state Screensaver {
entry do screen = 0
}
if touch go to Pages shallow history
}
Superstate M was left while its inner state J was active. Later go to M history fires. Which of these happens in that tick?
Show the answer

Answer D: J is entered again: its entry action runs, and M’s local variables are initialised again

Resuming with history is an entry like any other: M and J are entered, their entry actions run and their locals are initialised. Only the choice of the inner state comes from history.

A chart has a superstate On that is entered only by if power go to On. Inside On, a transition if menu go to Settings history leads to a nested superstate Settings. What does KIELER do with that history transition?
Show the answer

Answer C: It treats it as a plain go to Settings, without a warning

KIELER processes history transitions only into states of the top-level regions, and inside states that are themselves history targets. On is not one, so the history on Settings is dropped silently.

State B has entry do n++. The chart goes to B with go to B deferred in tick 6 and stays there. When does n++ run?
Show the answer

Answer C: Never during this visit

A deferred entry skips the entry actions for good. The immediate behaviour of B that waited (immediate transitions, immediate during actions) runs in tick 7, but entry actions are not postponed.

Key ideas

  • go to S history resumes S in the states it was in when it was last left, at every level; shallow history resumes only the level directly inside S.
  • Resuming is an entry: entry actions run again and local variables start again from their initial values. History restores states, not data.
  • KIELER ignores history transitions into nested states unless every state around them is also a history target. Keep history targets in top-level regions.
  • go to S deferred arrives quietly: S’s entry actions are skipped and its immediate behaviour waits a tick. Use it when the inputs of the arrival tick still belong to the job just finished. History does not record a deferred entry.
  • For a superstate, whether a deferred entry also delays the inside depends on whether all of its incoming transitions are deferred.

Next, Connector states: junctions where transitions meet and branch again within a tick.

Report a mistake on this page