diff --git a/codex/utils/asyncstatemachine.nim b/codex/utils/asyncstatemachine.nim index 9df86294..b3d2761a 100644 --- a/codex/utils/asyncstatemachine.nim +++ b/codex/utils/asyncstatemachine.nim @@ -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]()) diff --git a/tests/codex/utils/testasyncstatemachine.nim b/tests/codex/utils/testasyncstatemachine.nim index 89b5943a..d7331822 100644 --- a/tests/codex/utils/testasyncstatemachine.nim +++ b/tests/codex/utils/testasyncstatemachine.nim @@ -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