2016-08-05 54 views
0

我开始熟悉MSM增强库。我发现这个真正有趣的questions关于加入几个正交状态。如何使用MSM增强库运行同一子状态机的多个实例

此外,我发现在boost文档中重用父状态机中的子状态机的方法,并编写了几个简单的嵌套状态机。

但是,我无法围绕如何将这两件事结合在一起。

我的目标是分叉到相同的子状态机的几个独立的实例,并等到它们完成之后再返回到父级控制器。

但是,boost documentation说,它是不可能直接分叉状态机。

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

买票平面可以模型作为子状态机,你要求的价格,然后进行一些评估和比你可以购买它(取消和没有完成订单也是可能的)。但同样的道理可以适用于几家航空公司。 现在,我们假设我们想要创建一个软件来扫描市场并预订来自不同提供商的一定数量的票据。 当我们收到客户的订单时,我们询问市场,并决定从4家不同的航空公司购买(客户不介意)。 现在,4个子状态机将并行工作,只有当最后一个命令完成时,控制才会返回到父状态机。 (我知道这个例子并不好,但我希望你明白了)。

问题

是否有可能到餐桌,并使用相同的状态机的几个实例(或实现与伪状态几乎相同的效果)?状态机如何知道事件所指的是哪个子状态机?

如果有可能,请您指点我正确的方向?我知道这个增强文档example,但它并没有真正解决我的问题。

我处于项目的早期阶段,所以如果有必要,我仍然可以移动到不同的状态机库(boost状态图也在评估中)。

回答

1

我认为正交态与状态的不同部分很好地协同工作,但处理相同的事件。在你的情况下,你需要多个状态机实例。为了解决你的情况,我认为定义两个不同的状态机是更好的方法。他们没有父母和子女的关系,但彼此发送事件。

让我们说父状态机作为经理,子状态机作为工人。这里是两个分离的状态机:

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  | 
    +-----------+ 

我相信状态机可以说明您的示例场景。这里是代码: http://melpon.org/wandbox/permlink/JLkDaZBpvnAYLn5E

注意:上面的在线编译器输出有时不稳定,但我检查了我的本地环境的代码,并正常工作。

我在main()发送票价发现事件。这不是真的。也许从系统的其他部分接收价格数据。但这不是重点。

为了在状态机之间发送事件,我使用了msm :: back :: state_machine的shared_ptr。我需要让状态机的后端调用process_event,但模板参数Fsm是前端。所以我将状态机后端的weak_ptr作为成员变量嵌入状态机的前端。当我想调用process_event()时,使用get_sm()成员函数获取后端的shared_ptr。

在这种情况下,取消事件从管理器发送到worker。并发现事件是从工人发送给经理。

如果你想运行工为不同的线程,则需要使用互斥如下:

http://melpon.org/wandbox/permlink/TrexYnffiwEpazNk

见行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; 
} 
+0

非常感谢你为你的努力,我想我一定能建立在你的方法。我会仔细研究你的例子,再次感谢。 –

相关问题