显然,boost包含两个独立的状态机库:Statechart和Meta State Machine(MSM).标语给出了非常相似的描述:
你知道两者之间的主要区别和选择考虑因素是什么?
我正在尝试使用 boost::msm 库在我的代码中创建一个状态机。有谁知道一种获取状态的字符串名称(不是 int id)的方法吗?我正在尝试将其用于日志记录/调试目的。例如,在 no_transition 函数中,我获得了状态 ID,但我正在尝试获得一个名称,以便更容易阅读:
template <class Event ,class Fsm>
void no_transition(Event const& e, Fsm& fsm, int stateId)
{
//This is what I'm trying:
auto state = fsm.get_state_by_id(stateId); //This returns a boost::msm::front::default_base_state. Anything I can override in there to set a name?
const char* stateName = state->getStateName(); //I want to do something like this since I can do e.getEventId()
print("FSM rejected the event %s as there is no transition from current state %s (%d)\n", e.getEventId(), stateName, stateId); …Run Code Online (Sandbox Code Playgroud) 我正在使用新的Boost 1.44.0 MSM库来生成状态机.在这个状态机中有两类事件class1和class2.class1事件可以由任一状态进行处理S1或S2同时class2事件只能通过状态进行处理S2.
特殊class1事件upgrade_req请求从州S1到州的升级S2.
我在Boost :: MSM中实现了如下:
// State S1 and S2 allow any class1 events
struct class1 {};
// Only state S2 allows class2 events
struct class2 {};
// an upgrade request is a class1 event that requests an upgrade to state 2
struct upgrade_req : public class1 {};
struct MyFSM : public msm::front::state_machine_def< MyFSM >
{ …Run Code Online (Sandbox Code Playgroud) 我有大约 40 个转换的根状态机(包括四个子状态机)。一切都运行良好,但是当我开始提高转换数量时,编译时间显着增加(大型状态机的开发变得地狱)。我尝试使用 boost::msm::back::favor_compile_time 策略,并将子机器拆分为多个翻译单元,但没有效果。有人对这个问题有一些解决方法吗?Boost - 1.53,编译器 - MSVC 2012,处理器 - Intel i7
更新:减少时间的最佳方法 - 从项目中删除 boost msm
我打算将boost.msm与包含正交区域的复合概念一起使用.我想在退出时同步所有正交区域.换句话说:当且仅当所有区域都达到其最后状态时,才会激活我的复合后的状态.
UML 2.4"超结构"提出了连接伪状态(即第15.3.8章).在boost中,有一个fork但我找不到其对应连接的任何实现.
boost.msm中没有join伪状态吗?如何将boost伪状态的概念应用于boost.msm?
我想将 boost::msm statemachine 的实现拆分为多个文件。我正在寻找类似的东西:
1) 每个州一个标头
2)主状态机(最外面的SM)的一个标头但我不知道这个文件应该如何编写
3)使用SM的客户端代码。
我提出的内容如下(无法编译,给出以下形式的错误:“无效使用不完整类型”和其他错误)。
第一个示例状态:
//State1.h
#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;
struct State1:msmf::state<>
{
// Entry action
template <class Event,class Fsm>
void on_entry(Event const&, Fsm&) const {
std::cout << "State1::on_entry()" << std::endl;
}
// Exit action
template <class Event,class Fsm>
void on_exit(Event const&, Fsm&) const {
std::cout << "State1::on_exit()" << std::endl;
}
};
Run Code Online (Sandbox Code Playgroud)
第二个样本状态:
//State2.h
#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include …Run Code Online (Sandbox Code Playgroud) 有没有办法访问 boost msm 中的所有状态(不仅是活动状态)?例如,放置在状态中的所有 UI 控件都应该在调整大小事件时调整大小,无论它们的状态是否活动。
更新:让我澄清一下,我需要某种迭代器来遍历我的状态机创建的所有对象状态。
更新#2:下面是一个示例。我需要调用所有状态的resize方法。
struct EventOne {};
struct EventTwo {};
struct StateOne : public state<> {
void resize() { }
};
struct StateTwo : public state<> {
void resize() { }
};
struct MyFsm : public state_machine_def<MyFsm> {
typedef int no_exception_thrown;
typedef StateOne initial_state;
struct transition_table : boost::mpl::vector<
// Start, Event, Next, Action, Guard
Row< StateOne, EventOne, StateTwo, none, none >,
Row< StateTwo, EventTwo, StateOne, none, none >
> {
};
};
typedef boost::msm::back::state_machine<MyFsm> Fsm;
Run Code Online (Sandbox Code Playgroud) 这是给那些有 Boost MSM 经验的人一个问题。我有一个用 Boost MSM 实现的非常大的状态机,最后今天我用完了向量限制 50(有太多事件进入我的状态机,这是无法避免的)。我已经创建了更高的向量标头(vector60、vector70 等),但我想将我的状态机作为一个整体进行压缩。
问题是,MSM 是否支持分层状态机。例如(如果我错了,请纠正我),在分层状态机中,如果在特定状态下未处理事件,则该事件将被转发到当前状态的父状态等等。
作为减少转换表大小的一部分,我希望创建一个父状态,其中将处理具有公共处理程序的事件,从而减少转换表的大小。
任何建议/意见表示赞赏。
谢谢
我试图通过使用 boost MSM 状态机的显式模板实例化来减少项目的编译时间。但是,每当我添加显式模板实例化时,我的项目都不会编译。
您可以使用此处文档中的示例找到问题的示例:http://coliru.stacked-crooked.com/a/9850cae23afdada2。(这是一个人为的示例,因为只有一个翻译单元,但错误与我在项目中使用显式模板实例化时的错误相同。)
有谁知道如何解决这些编译错误?
/usr/local/include/boost/msm/back/state_machine.hpp: In instantiation of 'boost::msm::back::state_machine<A0, A1, A2, A3, A4>::deferred_events_queue_t& boost::msm::back::state_machine<A0, A1, A2, A3, A4>::get_deferred_queue() [with A0 = player_; A1 = boost::parameter::void_; A2 = boost::parameter::void_; A3 = boost::parameter::void_; A4 = boost::parameter::void_; boost::msm::back::state_machine<A0, A1, A2, A3, A4>::deferred_events_queue_t = std::deque<std::pair<boost::function<boost::msm::back::HandledEnum()>, bool>, std::allocator<std::pair<boost::function<boost::msm::back::HandledEnum()>, bool> > >]':
main.cpp:271:27: required from here
/usr/local/include/boost/msm/back/state_machine.hpp:1346:40: error: 'struct boost::msm::back::state_machine<player_>::deferred_msg_queue_helper<boost::msm::back::state_machine<player_>, int>' has no member named 'm_deferred_events_queue'
return m_deferred_events_queue.m_deferred_events_queue;
~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
...
Run Code Online (Sandbox Code Playgroud) For some reasons, I can't setup the parameter of the state machine by constructor So I would like to access the public member function of the meta state machine by the back end. That is, I want something like
typedef msm::back::state_machine<player_> player;
player p;
p.get_front_end(); //get the address of the front end
p.get_front_end().set_param(34) //call the member function of front end
Run Code Online (Sandbox Code Playgroud)
Is this possible?Thanks
The other solution is pass the parameter into the state machine by Event.
p.process_event(open_theme(34));
Run Code Online (Sandbox Code Playgroud)