Understanding Statemachines, Part 4: Superstates 6

Posted by Micah Sat, 07 Apr 2007 21:19:00 GMT

Superstates

Often in statemachines, duplication can arise. For example, the vending machine in our examples may need periodic repairs. It’s not certain which state the vending machine will be in when the repair man arrives. So all states should have a transition into the Repair Mode state.


Diagram 1 - Without Superstates

In this diagram, both the Waiting and Paid states have a transition to the Repair Mode invoked by the repair event. Duplication! We can dry this up by using the Superstate construct. See below:


Diagram 2 - With Superstates

Here we introduce the Operational superstate. Both the Waiting and Paid states are contained within the superstate which implies that they inherit all of the superstate’s transitions. That means we only need one transition into the Repair Mode state from the Operational superstate to achieve the same behavior as the solution in diagram 1.

One statemachine may have multiple superstates. And every superstate may contain other superstates. ie. Superstates can be nested.

History State

The solution in diagram 2 has an advantage over diagram 1. In diagram 1, once the repair man is done he triggers the operate event and the vending machine transitions into the Waiting event. This is unfortunate. Even if the vending machine was in the Paid state before the repair man came along, it will be in the Waiting state after he leaves. Shouldn’t it go back into the Paid state?

Superstates come with the history state which solves this problem. Every superstate will remember which state it is in before the superstate is exited. This memory is stored in a pseudo state called the history state. Transitions that end in the history state will recall the last active state of the superstate and enter it.

You can see the history state being use in diagram 2. In this solution, the history state allows the vending machine to return from a repair session into the same state it was in before, as though nothing happened at all.

Code

The following code builds the statemachine in diagram 2. Watch out for the _H. This is how the history state is denoted. If you have a superstate named foo, then it’s history state will be named foo_H.

require 'rubygems'
require 'statemachine'

vending_machine = Statemachine.build do
  superstate :operational do
    trans :waiting, :dollar, :paid
    trans :paid, :selection, :waiting
    trans :waiting, :selection, :waiting
    trans :paid, :dollar, :paid

    event :repair, :repair_mode,  Proc.new { puts "Entering Repair Mode" }
  end

  trans :repair_mode, :operate, :operational_H, Proc.new { puts "Exiting Repair Mode" }

  on_entry_of :waiting, Proc.new { puts "Entering Waiting State" }
  on_entry_of :paid, Proc.new { puts "Entering Paid State" }
end

vending_machine.repair
vending_machine.operate
vending_machine.dollar
vending_machine.repair
vending_machine.operate

Output:

Entering Repair Mode
Exiting Repair Mode
Entering Waiting State
Entering Paid State
Entering Repair Mode
Exiting Repair Mode
Entering Paid State

Next we should cover pseudo states.

Comments

Leave a response

  1. Raindog 6 days later:

    Thanks for these tutorials, I’ve really enjoyed them and plan on using statemachine gem to implement some game logic for a simple enemy.

  2. wlt 3 months later:

    These tutorials is great! waiting for your next:)

  3. darren@pulsipher.org 3 months later:

    Great stuff. I was thinking I might have to do this myself, I am glad this has been done already.

  4. Raindog 3 months later:

    I was wondering if you could post a tutorial and use a complex statemachine as the example, perhaps one with multiple superstates, etc.

    Thanks!

  5. luc 8 months later:

    Same problem as tutor 3:

    problem with ‘onentryof’

    Example output:

    Entering Waiting State <— wrong msg Entering Repair Mode Exiting Repair Mode Entering Waiting State Entering Paid State Entering Repair Mode Exiting Repair Mode Entering Paid State

  6. Heg about 1 year later:

    Thank you very much for the gem and the articles - I’ve enjoyed the series very much!!

Comments