C++ Boost Statechart 与元状态机
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4275602/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Boost Statechart vs. Meta State Machine
提问by FireAphis
Apparently boost contains two separate libraries for state machines: Statechartand Meta State Machine(MSM). The taglines give very similar descriptions:
显然 boost 包含两个独立的状态机库:Statechart和Meta State Machine(MSM)。标语给出了非常相似的描述:
- Boost.Statechart - Arbitrarily complex finite state machines can be implemented in easily readable and maintainable C++ code.
- Meta State Machine - A very high-performance library for expressive UML2 finite state machines.
- Boost.Statechart - 任意复杂的有限状态机可以用易于阅读和维护的 C++ 代码实现。
- 元状态机 - 用于表达性 UML2 有限状态机的非常高性能的库。
Do you know what are the key differences and what are considerations in choosing between the two?
您是否知道主要区别是什么以及在两者之间进行选择时要考虑哪些因素?
采纳答案by Christophe Henry
As there seems to be much interest, please allow me to give my (obviously biased) opinion, which should therefore be taken with a grain of salt:
由于似乎有很多兴趣,请允许我发表我的(显然有偏见的)意见,因此应该持保留态度:
- MSM is much faster
- MSM requires no RTTI or anything virtual
- MSM has a more complete UML2 support (for example internal transitions, UML-conform orthogonal regions)
- MSM offers a descriptive language (actually several). For example, using the eUML front-end, a transition can be described as Source + Event [Guard] / Action == Target
- MSM will make your compiler suffer for bigger state machines, so you will need a pretty recent compiler (g++ >= 4.x, VC >= 9)
- MSM要快得多
- MSM 不需要 RTTI 或任何虚拟的东西
- MSM 有更完整的 UML2 支持(例如内部转换、符合 UML 的正交区域)
- MSM 提供了一种描述性语言(实际上有几种)。例如,使用 eUML 前端,转换可以描述为 Source + Event [Guard] / Action == Target
- MSM 会使您的编译器受制于更大的状态机,因此您将需要一个相当新的编译器(g++ >= 4.x,VC >= 9)
You can make yourself a better opinion by looking for comments posted during the review of MSM. This subject was much discussed on the developer list.
您可以通过查看 MSM 审核期间发布的评论来使自己获得更好的意见。这个主题在开发人员列表中被广泛讨论。
回答by Christophe Henry
As Christophe has already mentioned, one of the key differences between the two libraries is runtime performance. While MSM probably offers the best you can get here, Statechart consciously trades memory and processor cycles towards better scalability.
正如 Christophe 已经提到的,这两个库之间的主要区别之一是运行时性能。虽然 MSM 可能提供了您所能得到的最好的结果,但 Statechart 有意识地将内存和处理器周期换为更好的可扩展性。
With Boost.Statechart you can spread the layout(i.e. states, transitions) of your state machine over multiple translation units (cpp files) in ways you can't with MSM. This allows you to make the implementation of large FSMs more maintainable and get much faster compilation than with MSM.
使用 Boost.Statechart,您可以以 MSM 无法实现的方式将状态机的布局(即状态、转换)分布到多个翻译单元(cpp 文件)上。这使您可以使大型 FSM 的实现更易于维护,并且编译速度比 MSM 快得多。
Whether or not the performance overhead of Statechart compared to MSM will actually be significant for your application is often quite easy to answer when you ask yourself how many events your app will have to process per second.
当您问自己您的应用程序每秒必须处理多少事件时,Statechart 与 MSM 相比的性能开销对于您的应用程序是否真的很重要,通常很容易回答。
Assuming a moderately complex FSM implemented with Boost.Statechart, here are a few ballpark numbers:
假设使用 Boost.Statechart 实现了一个中等复杂的 FSM,这里有一些大致的数字:
- Most current PC hardware will easily cope with >100'000 events per second
- Even veryresource-constrained hardware will be able to process a few hundred events per second.
- 大多数当前的 PC 硬件可以轻松应对每秒超过 100,000 个事件
- 即使是资源非常有限的硬件也能够每秒处理几百个事件。
Regarding CPU load, if the number of events to process is much lower than these numbers, Boost.Statechart overhead compared to MSM will almost certainly not be noticeable. If the number is much higher, you're definitely better off with MSM.
关于 CPU 负载,如果要处理的事件数量远低于这些数字,则与 MSM 相比,Boost.Statechart 开销几乎肯定不会引起注意。如果数字要高得多,那么 MSM 对您来说肯定会更好。
More in-depth information on the performance/scalability tradeoffs can be found here: http://www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html
有关性能/可扩展性权衡的更深入信息,请访问:http: //www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html
回答by blaze
While coding my own PPP implementation I used Statechart for three reasons: 1) Statechart is simpler and has clearer documentation; 2) I really dislike UML :)
在编写自己的 PPP 实现时,我使用 Statechart 有以下三个原因:1) Statechart 更简单,文档更清晰;2) 我真的不喜欢 UML :)
Boost docs say MSM is at least 20 times faster, but compiles pretty slow for large FSM.
Boost 文档说 MSM 至少要快 20 倍,但对于大型 FSM 来说编译速度很慢。
回答by Gordon M. Smith
Some time ago I began with Statechart and moved to MSM because it was easier to use in conjunction with asio from a single thread. I did not manage to mesh Statechart and its multithreading capabilities with my use of asio - it was likely some sort of newbie incomprehension of Statechart on my part. I found that MSM was easier to use as it did not address multithreading.
前段时间我开始使用 Statechart 并转移到 MSM,因为它更容易从单个线程与 asio 结合使用。我没有设法通过使用 asio 将 Statechart 及其多线程功能结合起来 - 这可能是我对 Statechart 的某种新手不理解。我发现 MSM 更易于使用,因为它没有解决多线程问题。
回答by da77a
In answer to Tim's late entry to the discussion (which also addresses one of the very early comments from Lev).
回答 Tim 迟到的讨论(这也解决了 Lev 早期的评论之一)。
As one of those who argued for exit separation from destructors in statechart (argument based on a real use case, about interaction with the real world i.e. I/O) way back when it was submitted to Boost I agree there can be issues in putting exit logic in destructors. David Abrahams unsurprisingly made persuasive arguments regarding exception safety as well. For those reasons Statechart doesn't require you to put logic in destructors - but it allows you to - with the usual advice.
作为那些在状态图中主张退出与析构函数分离的人之一(基于真实用例的论据,关于与现实世界的交互,即 I/O)早在它被提交给 Boost 时,我同意在退出时可能存在问题析构函数中的逻辑。不出所料,David Abrahams 也对异常安全提出了有说服力的论点。由于这些原因,Statechart 不要求您将逻辑放入析构函数中——但它允许您使用通常的建议。
Logic that should only ever run as part of a transition out of a state (not destruction of the statechart object as a whole) can (and should if there is also resource cleanup to do) be separated into a separate exit() action.
应该只作为状态转换的一部分运行的逻辑(而不是整个状态图对象的销毁)可以(并且应该如果还有资源清理要做)被分离到单独的 exit() 操作中。
For a "thin" state with no active state (resources), just entry/exit actions to perform, you can perform those actions in ctor and d'tor and make sure the constructor and destructor don't throw. There is no reason for them to - there is no state to perform RAII on - there is no evil in having the error handling in these places raise appropriate events. You may still need to consider whether you want exit actions that alter external state to run on state machine destruction though... and put them in exit action if you don't want them to occur in this case...
对于没有活动状态(资源)的“瘦”状态,只需执行进入/退出操作,您可以在 ctor 和 d'tor 中执行这些操作,并确保构造函数和析构函数不会抛出。他们没有理由 - 没有可以执行 RAII 的状态 - 在这些地方进行错误处理引发适当的事件并没有什么坏处。您可能仍然需要考虑是否希望改变外部状态的退出操作在状态机销毁时运行……如果您不希望它们在这种情况下发生,请将它们置于退出操作中……
Statechart models activation as instantiation of an object, so if your constructor has real work/activation/instantiation to do and if it is able to fail such that the state cannot be entered Statechart supports that by giving you the ability to map an exception to an event. This is handled in a way that works up the state hierarchy looking for an outer state that handles the exception event, analogous to the way the stack would have unwound for a call stack based invocation model.
Statechart 将激活建模为对象的实例化,因此如果您的构造函数有实际工作/激活/实例化要做,并且它能够失败以致无法进入状态,Statechart 通过让您能够将异常映射到事件。这是通过在状态层次结构中查找处理异常事件的外部状态的方式来处理的,类似于基于调用堆栈的调用模型的堆栈展开方式。
This is all well documented - I suggest you read the docs and try it. I suggest that you use destructors to clean up "software resources" and exit actions to perform "real-world exit actions".
这都是有据可查的 - 我建议您阅读文档并尝试一下。我建议您使用析构函数清理“软件资源”并退出操作以执行“现实世界的退出操作”。
It is worth noting note that exception propagation is a bit of a problem in all event driven environments, not just statecharts. It is best to reason about and include faults/errors in your statechart design and if and only if you can't handle them another way resort to exception mapping. At least that works for me - ymmmv....
值得注意的是,异常传播在所有事件驱动的环境中都是一个问题,而不仅仅是状态图。最好在状态图设计中推理并包含故障/错误,并且当且仅当您无法以另一种方式处理它们时才求助于异常映射。至少这对我有用 - ymmmv ....