[statemachine] remove template, replace with inheritable Machine/State

- remove `makeStateMachine` template, replace with inheritable Machine/State so that normal imports can be used
- rename `MachineType` to `Machine`
- rename `StateType` to `State`
This commit is contained in:
Eric Mastro 2023-02-14 17:19:32 +11:00 committed by Mark Spanbroek
parent 21527bb70f
commit d7b66611b3
No known key found for this signature in database
GPG Key ID: FBE3E9548D427C00
2 changed files with 43 additions and 45 deletions

View File

@ -2,55 +2,55 @@ import pkg/questionable
import pkg/chronos import pkg/chronos
import pkg/upraises import pkg/upraises
template makeStateMachine*(MachineType, StateType) = # template makeStateMachine*(Machine, State) =
type type
MachineType* = ref object of RootObj Machine* = ref object of RootObj
state: StateType state: State
running: Future[void] running: Future[void]
scheduled: AsyncQueue[Event] scheduled: AsyncQueue[Event]
scheduling: Future[void] scheduling: Future[void]
StateType* = ref object of RootObj State* = ref object of RootObj
Event = proc(state: StateType): ?StateType {.gcsafe, upraises:[].} Event = proc(state: State): ?State {.gcsafe, upraises:[].}
proc transition(_: type Event, previous, next: StateType): Event = proc transition(_: type Event, previous, next: State): Event =
return proc (state: StateType): ?StateType = return proc (state: State): ?State =
if state == previous: if state == previous:
return some next return some next
proc schedule*(machine: MachineType, event: Event) = proc schedule*(machine: Machine, event: Event) =
machine.scheduled.putNoWait(event) machine.scheduled.putNoWait(event)
method run*(state: StateType): Future[?StateType] {.base, upraises:[].} = method run*(state: State): Future[?State] {.base, upraises:[].} =
discard
proc run(machine: Machine, state: State) {.async.} =
try:
if next =? await state.run():
machine.schedule(Event.transition(state, next))
except CancelledError:
discard discard
proc run(machine: MachineType, state: StateType) {.async.} = proc scheduler(machine: Machine) {.async.} =
try: try:
if next =? await state.run(): while true:
machine.schedule(Event.transition(state, next)) let event = await machine.scheduled.get()
except CancelledError: if next =? event(machine.state):
discard if not machine.running.isNil:
await machine.running.cancelAndWait()
machine.state = next
machine.running = machine.run(machine.state)
asyncSpawn machine.running
except CancelledError:
discard
proc scheduler(machine: MachineType) {.async.} = proc start*(machine: Machine, initialState: State) =
try: machine.scheduling = machine.scheduler()
while true: machine.schedule(Event.transition(machine.state, initialState))
let event = await machine.scheduled.get()
if next =? event(machine.state):
if not machine.running.isNil:
await machine.running.cancelAndWait()
machine.state = next
machine.running = machine.run(machine.state)
asyncSpawn machine.running
except CancelledError:
discard
proc start*(machine: MachineType, initialState: StateType) = proc stop*(machine: Machine) =
machine.scheduling = machine.scheduler() machine.scheduling.cancel()
machine.schedule(Event.transition(machine.state, initialState)) machine.running.cancel()
proc stop*(machine: MachineType) = proc new*(_: type Machine): Machine =
machine.scheduling.cancel() Machine(scheduled: newAsyncQueue[Event]())
machine.running.cancel()
proc new*(_: type MachineType): MachineType =
MachineType(scheduled: newAsyncQueue[Event]())

View File

@ -5,8 +5,6 @@ import pkg/upraises
import codex/utils/asyncstatemachine import codex/utils/asyncstatemachine
import ../helpers/eventually import ../helpers/eventually
makeStateMachine(Machine, State)
type type
State1 = ref object of State State1 = ref object of State
State2 = ref object of State State2 = ref object of State