显然,boost包含两个用于状态机的独立库:Statechart和Meta State Machine(MSM)。标语给出了非常相似的描述:
您是否知道在两者之间选择的主要区别和考虑因素是什么?
答案 0 :(得分:112)
由于似乎有很大兴趣,请允许我提出我的(明显有偏见的)意见,因此应该采取一系列措施:
通过查找MSM审核期间发布的评论,您可以让自己更好。这个主题在开发人员名单上进行了很多讨论。
答案 1 :(得分:109)
正如Christophe已经提到的,两个库之间的关键差异之一是运行时性能。虽然MSM可能提供了最好的功能,但Statechart可以有意识地将内存和处理器周期换成更好的可扩展性。
使用Boost.Statechart,您可以通过多种翻译单元(cpp文件)以您无法使用MSM的方式传播状态机的布局(即状态,转换)。这使您可以使大型FSM的实现更易于维护,并且比MSM更快地编译。
当您问自己应用每秒要处理多少事件时,状态图与MSM相比的性能开销是否真的对您的应用程序来说实际上非常重要。
假设使用Boost.Statechart实现了一个中等复杂的FSM,这里有几个球场号码:
关于CPU负载,如果要处理的事件数远远低于这些数字,则与MSM相比,Boost.Statechart开销几乎肯定不会引人注意。如果这个数字要高得多,你肯定会更好地使用MSM。
有关性能/可扩展性权衡的更多深入信息,请访问: http://www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html
答案 2 :(得分:11)
在编写我自己的PPP实现时,我使用状态图有三个原因: 1)状态图更简单,文档更清晰; 2)我真的不喜欢UML:)
Boost docs说MSM的速度至少要快20倍,但对于大型FSM来说编译速度相当慢。
答案 3 :(得分:4)
前段时间我开始使用Statechart并转移到MSM,因为它更容易与单个线程中的asio一起使用。我没有设法使用asio来对Statechart及其多线程功能进行网格划分 - 这可能是某些新手对Statechart的不理解。我发现MSM更容易使用,因为它没有解决多线程问题。
答案 4 :(得分:2)
回答蒂姆迟到的讨论(这也是莱夫最早的评论之一)。
作为那些主张退出与状态图中的析构函数分离的人之一(基于真实用例的论证,关于与现实世界的交互,即I / O),当它被提交给Boost时,我认为可能存在问题将退出逻辑放在析构函数中。毫不奇怪,大卫亚伯拉罕也就异常安全提出了有说服力的论据。出于这些原因,Statechart并不要求您将逻辑放在析构函数中 - 但它允许您 - 使用通常的建议。
逻辑应该只作为状态转换的一部分运行(而不是作为一个整体破坏状态图对象)可以(并且如果还有资源清理要做)应该分成单独的exit()动作。
对于"瘦"没有活动状态(资源)的状态,只需要执行的进入/退出操作,您可以在ctor和dtor中执行这些操作,并确保构造函数和析构函数不会抛出。它们没有理由 - 没有任何状态可以执行RAII - 在这些地方进行错误处理引发适当的事件是没有恶意的。您可能仍需要考虑是否需要退出操作来改变外部状态以在状态机销毁时运行...并且如果您不希望它们在这种情况下发生,则将它们置于退出操作中...
状态图将激活模型化为对象的实例化,因此如果您的构造函数具有要进行的实际工作/激活/实例化,并且如果它能够失败以致无法输入状态,则状态图通过使您能够映射事件的例外。这是以一种处理状态层次结构的方式处理的,它寻找处理异常事件的外部状态,类似于堆栈为基于调用堆栈的调用模型解开的方式。
这一切都有详细记录 - 我建议你阅读文档并试一试。我建议您使用析构函数来清理软件资源"并退出行动以执行"现实世界退出行动"。
值得注意的是,在所有事件驱动的环境中,异常传播都是一个问题,而不仅仅是状态图。最好在状态图设计中推理并包含错误/错误,当且仅当您无法以另一种方式处理异常映射时才能处理它们。至少这对我有用 - ymmmv ....