Chances are that if you have previously used an FSM, it probably only supported the concept of being in a single state at any given moment.

UML2 and FSM2 support the concept of nested states and concurrent states. Whenever you use nested states or Concurrent Regions your FSM2 state machine may at times be in multiple concurrent states.

Because we have multiple concurrent states, you can't just ask FSM2 what the current state is. Instead, you have to ask what the current set of states are.

In UML2 they refer to the current set of states as the State Configuration, in FSM2 we refer to it as the 'StateOfMind'. A StateOfMind is an object that reflects the current set of states of the state machine.

The primary access path to the StateOfMind is via:


The allows you to respond to state changes by combining it with the likes of StreamBuilder. You then use StateOfMind.isInState to check for a particular state.

You should also look to using the onEnter, onExit, and sideEffect methods on states and transitions as these are the most effective ways of hooking into the state machine.

State Paths

The StateOfMind doesn't just hold a set of States, rather it holds a set of state paths.

UML2 describes the State Configuration (the equivalent of our StateOfMind) as a tree of states starting at the root state. There is a branch on that tree for each active state.

FSM2 takes a slightly different approach to optimise access.

For each active state, we keep a list of ancestor states starting at the active state back to the root state.

An FSM2 state machine can have multiple roots (under the hood we implement a VirtualRoot which all of these roots use as a parent).

If you look at the following simplified example you see we have two root nodes 'Alive' and 'Dead' each of which have nested child states.

In turn, we can see that the 'Dead' state has two child states, 'InHeaven' and 'inHell', and that InHeavan has a subsequent child state 'Buddhist'. So we could say that this FSM is a three-level tree with Buddhist as a 3rd level node in the tree. The deepest nodes on each branch (such as Buddhist) are referred to as Leaf Nodes.

var machine = StateMachine.create((g) => g
    ..state<Alive>((b) => b
      ..state<Young>((b) {})
      ..state<MiddleAged>((b) {})
      ..state<Old>((b) => b))
    ..state<Dead>((b) => b
      ..state<InHeaven>((b) => b
        ..state<Buddhist>((b) {}))
      ..state<InHell>((b) => b
        ..state<Christian>((b) => b
        ..state<Catholic>((b) {})
        ..state<SalvationArmy>((b) {}))))

If Buddhist is the current active state, then the StateOfMind would contain one state path:

Buddhist -> InHeaven -> Dead

Each of the above states, Buddhist, InHeaven, and Dead are now all considered active.

Last updated