我正在寻找实现有限状态机(FSM)的方法,这让我第一次接触到协程。
我看到了几个示例(这里、这里和这里),它们表明一个状态机可以通过单个协程来实现。然而,我注意到所有这些状态机都有一个共同点,即除了循环之外,它们都是树形结构 - 也就是说,从起始节点到每个其他节点都只有一条路径(不包括循环),并且这与由嵌套的if
提供的分层控制流相吻合。我试图建模的状态机至少有一个状态从起始节点到达该状态的路径不止一条(如果消除循环,则为有向无环图)。我无法想象什么样的控制流(除了goto
)能够实现这一点,或者是否可能实现。
另外,我可以使用单独的协程来处理每个状态并向某种调度协程进行yield。但是,在这种设置中,我没有看到使用协程相对于常规函数的特别好处。
下面是我尝试建模的一个简单状态机:
A --'a'--> B
A --'b'--> C
B --'a'--> C
B --'b'--> A
C --'a'--> A
C --'b'--> B
以下是我目前的进展。最终实现将采用Boost C++,但我正在使用Python进行原型设计。
#!/usr/bin/python3
def StateMachine():
while True:
print(" Entered state A")
input = (yield)
if input == "a":
print(" Entered state B")
input = (yield)
if input == "a":
# How to enter state C from here?
pass
elif input == "b":
continue
elif input == "b":
print(" Entered state C")
input = (yield)
if input == "b":
continue
elif input == "a":
# How to enter state B from here?
pass
if __name__ == "__main__":
sm = StateMachine()
sm.__next__()
while True:
for line in input():
sm.send(line)
这个协程能否被修复以正确地模拟状态机?或者我需要另外想办法来处理它?
goto
进入树的中间或者一个变量来保存状态,以便可以从顶部重新进入树。 - laindirgoto
,但C和C++有,我将编辑我的答案以包括在C中使用goto
的示例。我认为这不是最好的方法,但它确实演示了可能的方法。 - laindirgoto
,这使得代码大幅度简化)。它可能应该处理除了 'a' 和 'b' 之外的其他输入(也许只需返回 0)。顶部的#define
有点棘手,但允许您在标准C中实现生成器,带一些语法糖。Python在幕后基本上也是用其yield
关键字做着同样的事情。 - laindir#define
宏真正意义所在。 - laindir