[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/upraises
template makeStateMachine*(MachineType, StateType) =
# template makeStateMachine*(Machine, State) =
type
MachineType* = ref object of RootObj
state: StateType
running: Future[void]
scheduled: AsyncQueue[Event]
scheduling: Future[void]
StateType* = ref object of RootObj
Event = proc(state: StateType): ?StateType {.gcsafe, upraises:[].}
type
Machine* = ref object of RootObj
state: State
running: Future[void]
scheduled: AsyncQueue[Event]
scheduling: Future[void]
State* = ref object of RootObj
Event = proc(state: State): ?State {.gcsafe, upraises:[].}
proc transition(_: type Event, previous, next: StateType): Event =
return proc (state: StateType): ?StateType =
if state == previous:
return some next
proc transition(_: type Event, previous, next: State): Event =
return proc (state: State): ?State =
if state == previous:
return some next
proc schedule*(machine: MachineType, event: Event) =
machine.scheduled.putNoWait(event)
proc schedule*(machine: Machine, event: 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
proc run(machine: MachineType, state: StateType) {.async.} =
try:
if next =? await state.run():
machine.schedule(Event.transition(state, next))
except CancelledError:
discard
proc scheduler(machine: Machine) {.async.} =
try:
while true:
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 scheduler(machine: MachineType) {.async.} =
try:
while true:
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: Machine, initialState: State) =
machine.scheduling = machine.scheduler()
machine.schedule(Event.transition(machine.state, initialState))
proc start*(machine: MachineType, initialState: StateType) =
machine.scheduling = machine.scheduler()
machine.schedule(Event.transition(machine.state, initialState))
proc stop*(machine: Machine) =
machine.scheduling.cancel()
machine.running.cancel()
proc stop*(machine: MachineType) =
machine.scheduling.cancel()
machine.running.cancel()
proc new*(_: type MachineType): MachineType =
MachineType(scheduled: newAsyncQueue[Event]())
proc new*(_: type Machine): Machine =
Machine(scheduled: newAsyncQueue[Event]())

View File

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