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.
Coming back where you left off
Section titled “Coming back where you left off”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.
Diagrams
PlayerRestart
PlayerHistory
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 | input bool next | input bool call | input bool hangUp | PlayerRestart: output int track | PlayerRestart: Active state of the chart | PlayerRestart: Active state of the region of Playing | PlayerHistory: output int track | PlayerHistory: Active state of the chart | PlayerHistory: Active state of the region of Playing |
|---|
Guided tour, 9 ticks, the same inputs for both charts:
- next = false, call = false, hangUp = falseTick 1 enters
PlayingandTrack1in both players (track= 1). - next = true
Track1toTrack2(track= 2). - next = falseListening to track 2.
- call = trueA call comes in: both players leave
PlayingforOnCall(track= 0).PlayerHistoryremembers thatPlayingwas inTrack2. - call = false, hangUp = trueHang up.
PlayerRestart:go to PlayingentersPlayingafresh, in its initial stateTrack1(track= 1).PlayerHistory:go to Playing historyresumesTrack2, and sinceTrack2is entered again, its entry action runs (track= 2). - hangUp = false
PlayerRestarthas lost its place;PlayerHistorycarries on with track 2. - next = true, call = true
nextandcallin the same tick.go to OnCallis a weak abort, so the inside ofPlayingfirst takes its last step:Track1toTrack2inPlayerRestart,Track2toTrack3inPlayerHistory. Then both go toOnCall(track= 0). - next = false, call = false, hangUp = trueHang up.
PlayerRestartstarts at track 1 again.PlayerHistoryresumes the state entered last,Track3, the one reached in the abort tick (track= 3). - hangUp = falseTrack 1 in
PlayerRestart, track 3 inPlayerHistory.
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).
The rule
Section titled “The rule”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 setstrackback to 2. - History remembers the state that was entered last. In tick 7,
nextandcallarrive together.go to OnCallis a weak abort, so the inside ofPlayingfirst takes its last step, fromTrack2toTrack3(see Aborts). That step counts: in tick 8, history resumesTrack3. The one exception is a state entered withdeferred, which history does not record at all (below). - History belongs to the transition, not to the state. Every other transition into
Sstill starts it from its initial states. You can say so explicitly withgo to S reset, which is the same as writing nothing.
History restores states, not data
Section titled “History restores states, not data”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.
Diagram
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.
| Tick | call | hangUp |
|---|---|---|
| 1 | false | false |
| 2 | false | false |
| 3 | false | false |
| 4 | true | false |
| 5 | false | true |
| 6 | false | false |
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 = 0A 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.
Shallow and deep history
Section titled “Shallow and deep history”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.
Diagrams
MenuDeep
MenuShallow
Code
MenuDeep
@layout[elk.direction] DOWNscchart 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] DOWNscchart 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 | input bool menu | input bool home | input bool down | input bool right | MenuDeep: output int screen | MenuDeep: Active state of the chart | MenuDeep: Active state of the region of Settings | MenuDeep: Active state of the region of Settings.Display | MenuDeep: Active state of the region of Settings.Sound | MenuShallow: output int screen | MenuShallow: Active state of the chart | MenuShallow: Active state of the region of Settings | MenuShallow: Active state of the region of Settings.Display | MenuShallow: Active state of the region of Settings.Sound |
|---|
Guided tour, 10 ticks, the same inputs for both charts:
- menu = false, home = false, down = false, right = falseTick 1 enters
Homein both menus (screen= 0). - menu = trueThe first visit to
Settings: there is nothing to remember yet, so both start inDisplayandBrightness(screen= 11). - menu = false, right = true
BrightnesstoContrast(12). - right = false, home = trueBack
Home(0). Both charts remember whereSettingswas. - home = false, menu = trueBack to
Settingswith history.MenuDeep:historyis deep, soSettingsresumes inDisplay, andDisplayresumes inContrast(12).MenuShallow:shallow historyrestores only the level directly insideSettings, soDisplayis resumed but starts again inBrightness(11). - menu = false, down = true
DisplaytoSound, which starts inVolume(21) in both. - down = false, right = true
VolumetoBalance(22). - right = false, home = true
Home(0). - home = false, menu = trueDeep history resumes
Soundand, inside it,Balance(22). Shallow history resumesSound, starting inVolume(21). - menu = false
MenuDeepis on theBalancescreen,MenuShallowonVolume.
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:
Diagrams
MenuNested
MenuNestedFixed
Code
MenuNested
@layout[elk.direction] DOWNscchart 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] DOWNscchart 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 | input bool power | input bool menu | input bool home | input bool right | MenuNested: output int screen | MenuNested: Active state of the chart | MenuNested: Active state of the region of On | MenuNested: Active state of the region of On.Settings | MenuNestedFixed: output int screen | MenuNestedFixed: Active state of the chart | MenuNestedFixed: Active state of the region of On | MenuNestedFixed: Active state of the region of On.Settings |
|---|
Guided tour, 9 ticks, the same inputs for both charts:
- power = false, menu = false, home = false, right = falseTick 1 enters
Offin both (screen= −1). - power = truePower on: the first visit to
Onstarts inHome(0). - menu = trueThe first visit to
Settings:Brightness(11). - menu = false, right = true
Contrast(12). - right = false, home = true
Home(0). - home = false, menu = trueBack to
Settingswith history.MenuNested: surprise,Settingsstarts again inBrightness(11).Onis not the target of a history transition, so KIELER silently treatsgo to Settings historyas a plaingo to Settings.MenuNestedFixed:Onis a history target (fromOff), so the history inside it works:Contrast(12). - menu = false, power = falsePower off:
Off(−1). - power = truePower on.
MenuNestedstartsOninHome(0).MenuNestedFixedentersOnwithshallow history, so it resumes inSettings, which starts again inBrightness(11). The fix changed what switching on does. HomeinMenuNested,BrightnessinMenuNestedFixed.
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. HereSettingsis 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.
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.
Deferred transitions
Section titled “Deferred transitions”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 duringactions 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:
Diagram
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 | input bool walk | output int chimes | output int steps | Active state of the chart |
|---|
Guided tour, 4 ticks:
- walk = falseTick 1 enters
Outside. - walk = true
go to Hall deferred:Hallis entered quietly. No chime, and its immediate transition waits. - walk = falseOne tick later the immediate transition fires (
steps= 1). The entry action never runs for this visit (chimesstays 0). - In
Room.
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.
What deferred is for
Section titled “What deferred is for”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:
Diagrams
FillerNormal
FillerDeferred
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 | input bool cup | input bool full | FillerNormal: output int fills | FillerNormal: Active state of the chart | FillerDeferred: output int fills | FillerDeferred: Active state of the chart |
|---|
Guided tour, 7 ticks, the same inputs for both charts:
- 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. - Both are
Filling. - full = trueThe cup is full. Nobody has taken it away yet, so
cupis still true in this tick.FillerNormal:go to ReadyentersReady, whose immediate transition seescupand starts filling the full cup again (2).FillerDeferred:go to Ready deferredarrives inReadyquietly, so its immediate transition waits (1). - full = false, cup = falseThe cup has been taken away.
FillerDeferred’sReadynow looks atcup, finds no cup, and waits.FillerNormalisFillingwith nothing under the spout. - cup = trueA new cup.
FillerDeferredstarts filling it (2).FillerNormalis still inFillingand counts nothing. - full = trueThe second cup is full and still there.
FillerNormalstarts on it again (3);FillerDeferredwaits a tick (2). - full = false, cup = falseThe cup is gone. Two cups:
FillerDeferredcounted two fills,FillerNormalthree.
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.
Deferred entry into a superstate
Section titled “Deferred entry into a superstate”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:
Diagrams
DeferredOnly
DeferredMixed
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 | input bool walk | input bool rush | DeferredOnly: output int outerEntry | DeferredOnly: output int innerEntry | DeferredOnly: output int step | DeferredOnly: Active state of the chart | DeferredOnly: Active state of the region of Inside | DeferredMixed: output int outerEntry | DeferredMixed: output int innerEntry | DeferredMixed: output int step | DeferredMixed: Active state of the chart | DeferredMixed: Active state of the region of Inside |
|---|
Guided tour, 5 ticks, the same inputs for both charts:
- walk = false, rush = falseTick 1 enters
Outside.rushstays false throughout:DeferredMixed’s normal transition intoInsideis never taken, but it is there. - walk = trueThe deferred entry into
Inside.DeferredOnly: every transition intoInsideis deferred, so KIELER postpones the whole entry by a tick, and nothing inside happens yet (innerEntry= 0).DeferredMixed:Insideis entered now; only its own entry action is skipped, andFirst’s entry action runs (innerEntry= 1). - walk = false
DeferredOnlyreally entersInsidenow:First’s entry action runs (innerEntry= 1). InDeferredMixed,First’s delayed transition fires at the normal time (step= 1). DeferredOnly’sFirstfires one tick later than after a normal entry (step= 1).Inside’s own entry action has run in neither chart (outerEntry= 0).- 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 intoInsideis deferred, KIELER replaces the entry by an extra state and a delayed transition. IfInsidealso had a normal incoming transition, its inner states would start in the deferred tick itself.
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.
Deep deferred
Section titled “Deep deferred”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:
Diagrams
HouseDeferred
HouseDeep
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 | input bool walk | HouseDeferred: output int chimes | HouseDeferred: output int lights | HouseDeferred: output int steps | HouseDeferred: Active state of the chart | HouseDeferred: Active state of the region of House | HouseDeep: output int chimes | HouseDeep: output int lights | HouseDeep: output int steps | HouseDeep: Active state of the chart | HouseDeep: Active state of the region of House |
|---|
Guided tour, 4 ticks, the same inputs for both charts:
- walk = falseTick 1 enters
Outsidein both charts. - walk = trueBoth enter
Housedeferred. Every transition intoHouseis deferred, so KIELER really enters it a tick later: in this tick nothing ofHousehappens in either chart. - walk = falseThe inside starts.
HouseDeferred: the inner initial stateHallis entered normally, so its entry action runs (lights= 1) and its immediate transition fires (steps= 1).HouseDeep:deep deferredextends the quiet arrival toHall, so its entry action is skipped (lights= 0); only its immediate transition runs (steps= 1). Neither chart runsHouse’s own entry action (chimes= 0). - 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 intoHouseis deferred, KIELER replaces the entry by an extra state and a delayed transition. IfHousealso had a normal incoming transition, its inner states would start in the deferred tick itself. - Note in
HouseDeep, line 6, column 5Because every transition intoHouseis deep deferred, KIELER replaces the entry by an extra state and a delayed transition. IfHousealso had a normal incoming transition, its inner states would start in the deferred tick itself.
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.
Deferred entries are not remembered
Section titled “Deferred entries are not remembered”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:
Diagram
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 | input bool walk | input bool out | input bool back | output int room | Active state of the chart | Active state of the region of House |
|---|
Guided tour, 6 ticks:
- walk = false, out = false, back = falseTick 1 enters
HouseandHall;Hall’s entry action setsroom= 1. - walk = true
go to Kitchen deferred: the transition’s own effect setsroom= 2, andKitchenis entered quietly. - walk = falseIn
Kitchen. - out = trueOut into the
Garden(room= 9).Housewas inKitchenwhen it was left. - out = false, back = true
go to House historyresumesHall, notKitchen:Kitchenwas entered withdeferred, so KIELER never recorded it.Hall’s entry action runs again (room= 1). - 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.
Try it
Section titled “Try it”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}Check your understanding
Section titled “Check your understanding”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.
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.
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 historyresumesSin the states it was in when it was last left, at every level;shallow historyresumes only the level directly insideS.- 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 deferredarrives 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.