Last active
August 27, 2020 14:22
-
-
Save spytheman/a8a9c2deaaaa2c168328535242a5ef91 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import sync | |
| enum FSMState { | |
| init = 0 | |
| state_a | |
| state_b | |
| state_c | |
| exit | |
| } | |
| enum FSMEvent { | |
| ev1 = 0 | |
| ev2 | |
| ev3 | |
| ev4 | |
| ev5 | |
| } | |
| [ref_only] | |
| struct FSM { | |
| mut: | |
| prev_state FSMState | |
| current_state FSMState | |
| last_event FSMEvent | |
| current_event FSMEvent | |
| } | |
| // define functions to handle transition from state x to state y | |
| fn fsm_init() &FSM { | |
| // place the structure on heap | |
| return &FSM{ | |
| prev_state: .init | |
| current_state: .init | |
| last_event: .ev1 | |
| current_event: .ev1 | |
| } | |
| } | |
| fn (fsm &FSM) get_state() FSMState { | |
| return fsm.current_state | |
| } | |
| fn (mut fsm FSM) set_state(new_state FSMState) { | |
| fsm.prev_state = fsm.current_state | |
| fsm.current_state = new_state | |
| } | |
| fn (fsm &FSM) get_event() FSMEvent { | |
| return fsm.current_event | |
| } | |
| fn (mut fsm FSM) set_event(new_event FSMEvent) { | |
| fsm.last_event = fsm.current_event | |
| fsm.current_event = new_event | |
| } | |
| // | |
| type FnTransitionCb = fn(fsm &FSM, new FSMState) | |
| fn nop_transition(mut fsm FSM, new FSMState) {} | |
| fn print_transition(mut fsm FSM, new FSMState) { | |
| println('move from current: $fsm.current_state to new: $new') | |
| } | |
| struct FSMTransition { | |
| old FSMState | |
| evt FSMEvent | |
| new FSMState | |
| cb FnTransitionCb | |
| } | |
| const ( | |
| /* transition table | |
| * state X event -> new state | |
| * -------------------------- | |
| * init X ev1 -> state_a | |
| * init X ev2 -> state_c | |
| * state_a X ev3 -> state_b | |
| * state_b X ev4 -> state_c | |
| * state_c X ev5 -> state_a | |
| * state_c X ev1 -> exit | |
| */ | |
| transitions = [ | |
| FSMTransition{.init, .ev1, .state_a, print_transition} | |
| FSMTransition{.init, .ev2, .state_c, print_transition} | |
| FSMTransition{.state_a, .ev3, .state_b, print_transition} | |
| FSMTransition{.state_b, .ev4, .state_c, print_transition} | |
| FSMTransition{.state_c, .ev5, .state_a, print_transition} | |
| FSMTransition{.state_c, .ev1, .exit, print_transition} | |
| ] | |
| ) | |
| fn (mut fsm FSM) next() (FSMState, FnTransitionCb) { | |
| cs := fsm.current_state | |
| ce := fsm.current_event | |
| for t in transitions { | |
| if cs == t.old && ce == t.evt { | |
| return t.new, t.cb | |
| } | |
| } | |
| println('undefined FSM State X FSM Event combination: ${cs}/${ce}') | |
| return cs, nop_transition | |
| } | |
| fn (mut fsm FSM) run(events chan FSMEvent) { | |
| for { | |
| mut working_event := <- events // this blocks until there is an event | |
| fsm.set_event(working_event) | |
| next_state, fn_call := fsm.next() | |
| fn_call(fsm, next_state) | |
| fsm.set_state(next_state) | |
| if next_state == .exit { | |
| break | |
| } | |
| } | |
| } | |
| // | |
| fn produce_events(ch chan FSMEvent) { | |
| // place few events on queue | |
| ch <- FSMEvent.ev1 | |
| ch <- FSMEvent.ev3 | |
| ch <- FSMEvent.ev4 | |
| ch <- FSMEvent.ev5 | |
| ch <- FSMEvent.ev3 | |
| ch <- FSMEvent.ev4 | |
| ch <- FSMEvent.ev3 // junk event here / should be filtered out, we are in state_c | |
| ch <- FSMEvent.ev4 // junk event here / should be filtered out, we are in state_c | |
| ch <- FSMEvent.ev1 | |
| } | |
| fn main() { | |
| println('start main()') | |
| mut fsm := fsm_init() | |
| ch_fsm_events := chan FSMEvent{cap: 1000} | |
| go produce_events(ch_fsm_events) | |
| fsm.run(ch_fsm_events) | |
| current_state := fsm.get_state() | |
| println('last FSMState: $current_state') | |
| println('end main()') | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment