显然 boost 包含两个独立的状态机库:Statechart和Meta State Machine (MSM)。标语给出了非常相似的描述:
- Boost.Statechart - 任意复杂的有限状态机可以用易于阅读和维护的 C++ 代码实现。
- Meta State Machine - 一个非常高性能的库,用于表达 UML2 有限状态机。
您知道在两者之间进行选择的主要区别是什么吗?
显然 boost 包含两个独立的状态机库:Statechart和Meta State Machine (MSM)。标语给出了非常相似的描述:
您知道在两者之间进行选择的主要区别是什么吗?
由于似乎有很多兴趣,请允许我给出我的(显然有偏见的)意见,因此应该持保留态度:
您可以通过查找 MSM 审核期间发布的评论来使自己获得更好的意见。这个主题在开发者名单上讨论了很多。
正如 Christophe 已经提到的,这两个库之间的主要区别之一是运行时性能。虽然 MSM 可能提供了您可以在这里得到的最好的东西,但 Statechart 有意识地用内存和处理器周期来换取更好的可扩展性。
使用 Boost.Statechart,您可以将状态机的布局(即状态、转换)分布在多个翻译单元(cpp 文件)上,而 MSM 则无法做到这一点。与使用 MSM 相比,这使您可以使大型 FSM 的实现更易于维护并获得更快的编译速度。
当您问自己应用程序每秒必须处理多少事件时,通常很容易回答与 MSM 相比,Statechart 的性能开销是否实际上对您的应用程序很重要。
假设使用 Boost.Statechart 实现了一个中等复杂的 FSM,这里有一些大概的数字:
关于 CPU 负载,如果要处理的事件数量远低于这些数字,则与 MSM 相比,Boost.Statechart 开销几乎肯定不会引起注意。如果这个数字要高得多,那么使用 MSM 肯定会更好。
可以在此处找到有关性能/可扩展性权衡的更深入信息:http: //www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html
在编写我自己的 PPP 实现时,我使用 Statechart 有三个原因: 1) Statechart 更简单,文档更清晰;2) 我真的不喜欢 UML :)
Boost 文档说 MSM 至少快 20 倍,但对于大型 FSM 而言编译速度相当慢。
前段时间,我从 Statechart 开始并转向 MSM,因为它更容易与单线程中的 asio 一起使用。我没有设法将 Statechart 及其多线程功能与我对 asio 的使用联系起来——这可能是我对 Statechart 的某种新手不理解。我发现 MSM 更容易使用,因为它没有解决多线程问题。
作为对 Tim 迟到讨论的回答(这也解决了 Lev 的早期评论之一)。
作为那些在状态图中主张退出与析构函数分离的人之一(基于真实用例的论点,关于与现实世界的交互,即 I/O),当它提交给 Boost 时,我同意退出可能存在问题析构函数中的逻辑。不出所料,David Abrahams 在异常安全方面也提出了有说服力的论点。由于这些原因,Statechart 不需要您将逻辑放入析构函数中 - 但它允许您使用通常的建议。
应该只作为状态转换的一部分运行的逻辑(而不是整个状态图对象的破坏)可以(如果还需要进行资源清理,也应该)分离到单独的 exit() 操作中。
对于没有活动状态(资源)的“瘦”状态,只需执行进入/退出操作,您可以在 ctor 和 d'tor 中执行这些操作,并确保构造函数和析构函数不会抛出。他们没有理由 - 没有执行 RAII 的状态 - 在这些地方进行错误处理引发适当的事件并没有什么坏处。您可能仍然需要考虑是否要更改外部状态的退出操作在状态机破坏时运行...如果您不希望它们在这种情况下发生,请将它们置于退出操作中...
Statechart 将激活建模为对象的实例化,因此,如果您的构造函数有真正的工作/激活/实例化要做,并且如果它能够失败以致无法进入状态,Statechart 通过让您能够将异常映射到事件。这是以一种方式处理状态层次结构,以寻找处理异常事件的外部状态,类似于堆栈为基于调用堆栈的调用模型展开的方式。
这一切都有据可查 - 我建议您阅读文档并尝试一下。我建议你使用析构函数来清理“软件资源”和退出动作来执行“现实世界的退出动作”。
值得注意的是,异常传播在所有事件驱动的环境中都是一个问题,而不仅仅是状态图。最好在您的状态图设计中推理并包含错误/错误,并且当且仅当您无法以另一种方式处理它们时才诉诸异常映射。至少这对我有用- ymmmv ....