Skip to content

Commit

Permalink
finalized documentation for fsm.
Browse files Browse the repository at this point in the history
  • Loading branch information
mdbergmann committed Oct 5, 2024
1 parent b25a21d commit db167ed
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 62 deletions.
90 changes: 90 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,94 @@ For example could a facade for the counter above look like this:

Alternatively, one can wrap an agent inside a class and provide methods for simplified access to it.

### Finite State Machine (FSM)

The Finite State Machine (FSM) model is a computational framework designed to model and manage systems that transition between various states based on inputs or events. This structured approach facilitates the handling of complex logic through defined state transitions and events.

#### Creating an FSM

To create an FSM, use the `make-fsm` function, which initializes an actor with state management capabilities.

(Additional API documentation can be found [here](https://mdbergmann.github.io/cl-gserver/index.html##SENTO.FSM:@FSM%20MGL-PAX:SECTION).)

1. **actor-context**: Specifies where the FSM is created, which can be an actor, an actor-context, or an actor-system.
2. **name**: A string that names the FSM.
3. **start-with**: A cons cell representing the initial state and associated data.
4. **event-handling**: A function structured using FSM macros to define the FSM's behavior upon receiving events.

#### Example: Traffic Light Controller FSM with Timeouts

This FSM simulates a traffic light controller and includes comprehensive state and transition handling, including timeouts.

```elisp
(defun make-traffic-light-fsm (actor-context)
(make-fsm
actor-context
:name "traffic-light-fsm"
:start-with '(red . ())
:event-handling (lambda ()
;; Define behavior in each state using when-state
(when-state ('red :timeout-s 10)
(on-event ('timer) :state-timeout
(goto-state 'green))
(on-event ('manual-override)
(stay-on-state '(:manual-override-engaged))
(log:info "Manual override activated")))
(when-state ('green :timeout-s 15)
(on-event ('timer) :state-timeout
(goto-state 'yellow)))
(when-state ('yellow :timeout-s 5)
(on-event ('emergency-stop)
(goto-state 'red)
(log:info "Emergency stop activated"))
(on-event ('timer) :state-timeout
(goto-state 'red)))
;; Handle state transitions
(on-transition ('(red . green))
(log:info "Transition from red to green"))
(on-transition ('(green . yellow))
(log:info "Transition from green to yellow"))
(on-transition ('(yellow . red))
(log:info "Transition from yellow to red"))
;; Stay on current state but update data
(on-event ('maintenance-check)
(stay-on-state '(:maintenance-required))
(log:info "Maintenance required"))
;; Handle unhandled events with specific and general catch
(when-unhandled ('unexpected-event)
(log:warn "Unexpected specific event caught"))
(when-unhandled (t :test #'typep)
(log:warn "Unhandled event caught: ~A" *received-event*)))))
```

#### Example Breakdown

- **actor-context**: Passed argument where the FSM operates.
- **name**: The FSM is named "traffic-light-fsm".
- **start-with**: The FSM begins in the 'red' state.
- **event-handling**: Utilizes various macros:
- `when-state`: Defines actions specific to each state and handles timeouts.
- `on-event ('timer)`: Transitions the FSM to the next state on timer events; handles timeouts with `:state-timeout`.
- `goto-state`: Transitions the FSM to a new state, optionally updating data and logging.
- `stay-on-state ('maintenance-check)`: Remains in the current state while updating state data.
- `on-transition`: Logs state transitions.
- General `when-unhandled` using `typep`: Catches all other unhandled events and logs them using the dynamic variable `*received-event*` for context.

#### Running the FSM

After setup, the FSM processes events, transitioning as defined. This setup ensures responsive and structured event-driven state management.

Incorporating timeout controls and a comprehensive fallback for unhandled events, this FSM elegantly manages complex state logic with powerful macro functionalities.

### Router

A `Router` is a facade over a set of actors. Routers are either created with a set of actors using the default constructor `router:make-router` or actors can be added later.
Expand Down Expand Up @@ -686,6 +774,8 @@ Previous 'self' and 'state' parameters are now accessible via `*self*` and `*sta

### Version history

**Version 3.3.3 (1.10.2024):** Bug fix for actor with dispatcher mailbox where the order of processing messages wasn't honoured.

**Version 3.3.2 (14.8.2024):** Primarily documentation changes in regards to `future`

**Version 3.3.0 (1.7.2024):** See: [Changelog](https://github.com/mdbergmann/cl-gserver/compare/3.2.1...3.3.0)
Expand Down
12 changes: 6 additions & 6 deletions documentation.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,12 @@
(pax:defsection @fsm (:title "Finite state machine")
(fsm:fsm class)
(fsm:make-fsm function)
(fsm:when-state function)
(fsm:on-event function)
(fsm:goto-state function)
(fsm:stay-on-state function)
(fsm:when-unhandled function)
(fsm:on-transition function)
(fsm:when-state pax:macro)
(fsm:on-event pax:macro)
(fsm:goto-state pax:macro)
(fsm:stay-on-state pax:macro)
(fsm:when-unhandled pax:macro)
(fsm:on-transition pax:macro)
(fsm:*received-event* variable)
(fsm:*event-data* variable)
(fsm:*state-data* variable)
Expand Down
Loading

0 comments on commit db167ed

Please sign in to comment.