State Machine Fundamentals

This page has interactive examples to help you learn about StateSmith state machines. The examples use real code generated by StateSmith from the svg diagrams below.

The same diagrams can generate code for any supported language.

Scroll on down!

Simple On Off

This simple state machine controls the below lightbulb's color.

Try using the buttons below to send events to the Ex01 state machine.

When the OFF state is entered, it runs the code light_off();.

When the ON1 state is entered, it runs the code light_blue();.

Actions on Transitions

Transitions can also execute action code.

The transition from state OFF to state ON1 runs the code count++;. Action code can call a function, modify a state machine or global variable, or do almost anything.

State machine variables count: 0

Add More States

Let's add some more states and colors!

This example is building up for the next one.

Adding An OFF Event?

A cleaner solution follows in Ex05...

What if we add an OFF event that shuts off the lightbulb no matter which state it is in?

We can have a transition from each ON state to the OFF state. This is OK for very small designs like this one, but doesn't scale well.

Nested States

Add a parent state, and a single transition.

First, we nest all the ON states inside of ON_GROUP.

Then, we add a single transition from ON_GROUP to OFF for the OFF event.

If none of the ON states handle the OFF event, then their parent ON_GROUP state will handle the event and transition to OFF.

In the next section, we will see how sharing transitions like this can make a HUGE improvement in our designs.

Hierarchical State Machines (HSMs)

A Hierarchical State Machine (HSM) is a Finite State Machine (FSM), but with super powers!

Let's add a few more states to our design to make it a smart lightbulb and see the MASSIVE difference a HSM can make.

Regular Flat FSM

This comes from a real life example. Transition spaghetti mess.

Don't laugh. I've seen things much worse than this. I once received a design that looked like this spaghetti FSM mess except much bigger.

There were many hidden bugs and we eventually reimplemented the state machine with StateSmith utilizing a nested HSM design.

HSM To The Rescue!

Clear. Maintainable. Intuitive. Productive. Non-Repetitive.

When I reimplemented the real life FSM spaghetti mess with StateSmith and HSMs, a ton of problems and bugs instantly vanished.

We no longer wasted time playing whack-a-mole with bugs and oversights in the super messy, ultra repetitive design specifications.

The diagram was also simple enough that we shared it with the client. We would actually modify the StateSmith diagram live with the client over video calls. It was an incredibly powerful communication tool.

Exit Actions

Run action code when a state is exited.

In this example, if the REGULAR_OPERATION state is ever exited, we can be sure that the light is turned off with exit / light_off();.

Exit actions are great for ensuring safety, and clean up code.

This example also shows how a single transition or general state behavior can act on multiple events (DIM, INCREASE).

Choice Pseudo States

Decisions, Decisions, Decisions.

You can get fancier than what is shown here (more choices, chaining choice pseudo states), but this shows the main functionality well.

It's a bit unorthodox to have the initial state in the middle of a state, but it helps the design fit a phone screen.

State machine variables count: 0

Please Consider Contributing

StateSmith needs more user feedback before it can hit version 1.0.

Please consider contributing (especially if you have web skills).

Thanks! - Adam

Scroll on...

Guards & Variables

State behaviors can also have guard conditions.

The transition from ON2 to ON_HOT has a guard condition [count >= 3]. This transition will only be taken on the INCREASE event if count >= 3.

Transition guards can be any code that evaluate to a boolean result. In this example, the guard tests a state machine variable, but it could call a function, a bunch of functions, do some math...

Another interesting thing in this example is that we specify the order of the ON2 behaviors for the INCREASE event. We want to run count++ before testing if we should transition with [count >= 3].

You can read more about state behaviors here.

State machine variables count: 0

Polled State Machines

Event driven vs. polled state machines. Choose 2.

All the state machines that we have seen so far have been event driven.

When you press a DIM button on this page, the state machine's event handler function is invoked with the proper event ID. StateSmith state machines are event driven. They just sit waiting for you to feed them the next event (no thread, or background CPU usage).

If you need to poll certain conditions, simply send the DO event to your state machine at the rate you want. You have full control over how and when the state machine runs. Very helpful for embedded systems and game development.

Any transition without an event specified will use the DO event. This is different than UML, but we found the UML way caused problems for most users.

This example "polls" its state machine by dispatching a DO event at the rate specified below. When the state machine runs, it "polls" (checks) its Switch input to determine whether it should transition. DO event count: 0

Acting on Time

State machines can react to any time source you choose.

You can use the current system time, a game time (that can be paused), a tick counter...

This example uses a timer t1 to transition back to state ON1 after 2.1 seconds.

In the future, we will make it easier to track time spent in a state.

Put It All Together!

Try using the buttons below to send events to the Ex10 state machine.

State machine variables count: 0

StateSmith Can Handle 300+ States

Its balanced algorithm efficiently supports both small and huge designs.
Large deeply nested designs perform well and are easy to debug.

There is no actual limit StateSmith can handle.
300+ is just the most I've used it with.

History Pseudo States

Deep history and custom history also supported.

Try getting to ON2, then send DIM event to exit ON group. Then send INCREASE event and you will see it return directly back to ON2.

Consuming Events

A child state can consume an event (deny ancestor state).

📺 3 minute video tutorial

This example is very similar to Ex10, but this time we want to stay in the ON_HOT state for 4.2 seconds no matter what. Sending events OFF or DIM to the ON_HOT state should do nothing.

We simply make ON_HOT consume the OFF and DIM events so that its parent ON_GROUP doesn't get a chance to see the events.

Have a lot of events to consume? Check out TriggerMaps.

This example may feel a bit contrived, but this ability for child states to consume an event is crucial for many applications like user interfaces.

Another fun feature of draw.io support is that you can place images anywhere and StateSmith will ignore them (the fire image).

Action Order

Exit -> Transition -> Enter

StateSmith follows the UML specification which states that a transition's action code is run after states have been exited and before states are entered.

Assume you are in the WATER state and the EV1 event is dispatched. You will see the following order of actions:

  1. log("water exited");
  2. log("beverage exited");
  3. log("tran action 1");
  4. log("food entered");
  5. log("tran action 2");
  6. log("sandwich entered");

🕹️ You can play with an actual example here (requires a desktop).

Exit Points

Handy Drawing Tool

📺 Entry and exit points video

Exit points are just a diagramming aid. The `exit_pt` state machine example could be drawn with state ON1 transitioning directly to the HALTED state when the OFF event is dispatched. It's the exact same thing.

Exit points are exceptionally helpful though because they allow you to visually collapse the ON_GROUP state in draw.io, but still have state ON1 transition to HALTED when the OFF event is dispatched. Visually collapsing states is a great way of managing large and complex state machines.

You can find the behavior syntax for exit points here.

🕹️ You can play with an actual example here (requires a desktop).

Entry Points

Like Exit Points

📺 Entry and exit points video

Entry points are just like exit points (see above section). They are great for working with visually collapsed states in draw.io. The `entry_pt` state machine example could be drawn with state SHUT_OFF transitioning directly to the ON1 state when the ON event is dispatched. It's the exact same thing.

You can find the behavior syntax for entry points here.

🕹️ You can play with an actual example here (requires a desktop).

DO Events Are Special

They aren't normally consumed

When an event is dispatched to a state machine, the active state first gets a chance to handle it. If it doesn't handle the event, then its parent gets a chance... all the way up to the state machine root.

There is one exception - the do event. The do event is special in that state behaviors don't normally consume it. This allows child and parent states to do some work all the way up the chain.

However, if a transition occurs, no other behaviors will be checked for any state. This also applies to the do event.

Assume you are in the WAIT state, the DO event is dispatched, and wait_count < X :

  1. transition guard [wait_count > X] is evaluated to false
  2. wait_count++;
  3. menu_count++;

Still in the WAIT state, the DO event is dispatched, and wait_count > X :

  1. transition guard [wait_count > X] is evaluated to true.
  2. transition occurs (no other state behaviors are checked).

Assume you are now in the WATER state, the DO event is dispatched, and water_count < Y :

  1. water_count++;
  2. transition guard [water_count > Y] is evaluated to false
  3. bev_count++;
  4. menu_count++;

🕹️ You can play with an actual example here (requires a desktop).

There is More

StateSmith has more features than are shown here.

Things like Deep History, Trigger Maps, Parent Alias...

You can find more info in the examples repo, and diagram-features.md.

More interactive samples are in the works.

Please Consider Contributing

StateSmith needs more user feedback before it can hit version 1.0.

Please consider contributing (especially if you have web skills).

Thanks! - Adam