C++ 如何使用MSM boost库运行同一子状态机的多个实例

C++ 如何使用MSM boost库运行同一子状态机的多个实例,c++,boost,C++,Boost,我越来越熟悉MSM boost库。我发现将几个正交状态连接起来非常有趣 此外,我在boost文档中找到了一种在父状态机中重用子状态机的方法,并且我编写了两个简单的嵌套状态机 然而,我无法思考如何将这两种东西混合在一起 我的目标是分岔到同一子状态机的多个独立实例,并等待其中一个实例完成,然后再将控件返回给父实例 然而,报告指出,不可能直接将fork转换为子状态机 注意(对forks也有效):目前,不可能使用子机器作为显式条目的目标。请使用输入伪状态以获得几乎相同的效果 示例 购买机票飞机可以建模为

我越来越熟悉MSM boost库。我发现将几个正交状态连接起来非常有趣

此外,我在boost文档中找到了一种在父状态机中重用子状态机的方法,并且我编写了两个简单的嵌套状态机

然而,我无法思考如何将这两种东西混合在一起

我的目标是分岔到同一子状态机的多个独立实例,并等待其中一个实例完成,然后再将控件返回给父实例

然而,报告指出,不可能直接将fork转换为子状态机

注意(对forks也有效):目前,不可能使用子机器作为显式条目的目标。请使用输入伪状态以获得几乎相同的效果

示例

购买机票飞机可以建模为子状态机,您请求一个价格,然后执行一些评估,然后您就可以购买它(取消和不完成订单也是可能的)。但同样的逻辑也适用于多家航空公司。 现在,让我们假设我们想要创建一个软件来扫描市场,并从不同的提供商那里预订一定数量的门票。 当我们收到客户的订单时,我们查询市场,决定从4家不同的航空公司购买(客户不介意)。 现在,4个子状态机将并行工作,只有在最后一个订单完成时,控件才会返回到父状态机。(我知道这个例子不太好,但我希望你能理解)

问题

是否可以分叉并使用同一状态机的多个实例(或者使用伪状态实现几乎相同的效果)?状态机如何知道事件在哪个子状态机上引用

如果可能的话,你能给我指一下正确的方向吗?我知道这个boost文档,但它并没有真正解决我的问题


我正处于项目的早期阶段,因此如果需要,我仍然可以转移到另一个状态机库(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;
}

非常感谢你的努力,我想我一定可以借鉴你的方法。我将仔细研究你们的例子,再次感谢。