C++ 如何使用MSM boost库运行同一子状态机的多个实例
我越来越熟悉MSM boost库。我发现将几个正交状态连接起来非常有趣 此外,我在boost文档中找到了一种在父状态机中重用子状态机的方法,并且我编写了两个简单的嵌套状态机 然而,我无法思考如何将这两种东西混合在一起 我的目标是分岔到同一子状态机的多个独立实例,并等待其中一个实例完成,然后再将控件返回给父实例 然而,报告指出,不可能直接将fork转换为子状态机 注意(对forks也有效):目前,不可能使用子机器作为显式条目的目标。请使用输入伪状态以获得几乎相同的效果 示例 购买机票飞机可以建模为子状态机,您请求一个价格,然后执行一些评估,然后您就可以购买它(取消和不完成订单也是可能的)。但同样的逻辑也适用于多家航空公司。 现在,让我们假设我们想要创建一个软件来扫描市场,并从不同的提供商那里预订一定数量的门票。 当我们收到客户的订单时,我们查询市场,决定从4家不同的航空公司购买(客户不介意)。 现在,4个子状态机将并行工作,只有在最后一个订单完成时,控件才会返回到父状态机。(我知道这个例子不太好,但我希望你能理解) 问题 是否可以分叉并使用同一状态机的多个实例(或者使用伪状态实现几乎相同的效果)?状态机如何知道事件在哪个子状态机上引用 如果可能的话,你能给我指一下正确的方向吗?我知道这个boost文档,但它并没有真正解决我的问题C++ 如何使用MSM boost库运行同一子状态机的多个实例,c++,boost,C++,Boost,我越来越熟悉MSM boost库。我发现将几个正交状态连接起来非常有趣 此外,我在boost文档中找到了一种在父状态机中重用子状态机的方法,并且我编写了两个简单的嵌套状态机 然而,我无法思考如何将这两种东西混合在一起 我的目标是分岔到同一子状态机的多个独立实例,并等待其中一个实例完成,然后再将控件返回给父实例 然而,报告指出,不可能直接将fork转换为子状态机 注意(对forks也有效):目前,不可能使用子机器作为显式条目的目标。请使用输入伪状态以获得几乎相同的效果 示例 购买机票飞机可以建模为
我正处于项目的早期阶段,因此如果需要,我仍然可以转移到另一个状态机库(boost statechart也在评估中) 我认为正交状态可以很好地处理状态的不同部分,但可以处理相同的事件。在您的情况下,需要创建多个状态机实例。为了解决您的问题,我认为定义两个不同的状态机是更好的方法。它们没有父关系和子关系,而是相互发送事件 假设父状态机作为管理器,子状态机作为工作器。以下是两个独立的状态机:
worker
+-----------+
+--|processing |
| | |
| +-----------+
| |
| | e_found(price) / a_notify(price) (send e_found(price) to the manager
| V
| +-----------+
| |processed |
| +-----------+
|e_cancel|
| V
| +-----------+
+->|end |
+-----------+
manager
+-------------------------------------------------------+
|comparing |
|entry/create 4 workers |
|e_found(price) / increment count and compare price, etc|
+-------------------------------------------------------+
| e_cancel/ propagate e_cancel to all workers
V
+-----------+
|end |
+-----------+
我相信状态机说明了您的示例场景。代码如下:
注意:上面的在线编译器输出有时是不稳定的,但我在本地环境中检查了代码,工作正常
我发送一个在main()中找到事件的票面价格。这不是真的。可能从系统的其他部分接收价格数据。但这不是一个关键点
为了在状态机之间发送事件,我使用msm::back::state_machine的shared_ptr。我需要让状态机的后端调用process_事件,但模板参数Fsm是前端。因此,我将状态机后端的弱ptr作为成员变量嵌入状态机的前端。当我想调用process_event()时,使用get_sm()成员函数获取后端的共享\u ptr
在此场景中,取消事件从管理器发送到工作器。并将发现的事件从worker发送到manager
如果要将工作线程作为不同的线程运行,则需要使用互斥锁,如下所示:
int main() {
auto m = manager::create();
m->workers_[0]->process_event(e_found {10});
m->workers_[1]->process_event(e_found {20});
m->process_event(e_cancel()); // Cancel !!
m->workers_[2]->process_event(e_found {30});
m->workers_[3]->process_event(e_found {40});
return 0;
}
见第100行和第192行
取消事件由经理处理并传播到所有工作人员。要测试取消操作,可以按如下方式插入取消事件:
int main() {
auto m = manager::create();
m->workers_[0]->process_event(e_found {10});
m->workers_[1]->process_event(e_found {20});
m->process_event(e_cancel()); // Cancel !!
m->workers_[2]->process_event(e_found {30});
m->workers_[3]->process_event(e_found {40});
return 0;
}
非常感谢你的努力,我想我一定可以借鉴你的方法。我将仔细研究你们的例子,再次感谢。