A fork is similar to an on transition in that it takes an Event and transitions the FSM to a new State.

The difference is that a fork transitions the FSM into a concurrent region (costate). The targets of onFork are the new states the FSM will be in once the transition completes.

All the targets of a fork must enter states within the same concurrent region.

A fork is normally paired with a join. The fork causes the FSM to enter a concurrent region, the join exits the concurrent region returning the FSM to a single state.

  return StateMachine.create((g) => g
    ..state<CheckingAir>((b) => b
      ..onFork<OnCheckAir>((b) => b<HandleFan>()<HandleLamp>(), condition: (s, e) => e.quality < 10)
      ..state<CleaningAir>((b) => b
        ..costate<HandleEquipment>((b) => b
          ..onJoin<WaitForGoodAir>((b) => b
          ..state<HandleFan>((b) {})
          ..state<HandleLamp>((b) {}))
        ..state<WaitForGoodAir>((b) {}))));

All of the target states MUST be the descendant of a single costate.

In the UML2 nomenclature a 'Fork' is a pseudo state. Which is a state that the FSM never actually stays in but rather instantaneously transitions through.

Even thought Fork is a pseudo state, FSM2 has model it as a transition as it fits more neatly into the builder pattern that we have used.

The onFork method takes an Event which is the event that triggers the fork.

..state<CheckingAir>((b) => b
  ..onFork<OnCheckAir>((b) => b<HandleFan>()<HandleLamp>()

In the above example, if the FSM is in the 'CheckingAir' state and an 'OnCheckAir' event occurs then the FSM enters the 'HandleFan' AND the 'HandleLamp' states which are both children of the 'HandleEquipment' concurrent region.

Last updated