我认为正交状态适用于状态的不同部分,但处理相同的事件。在您的情况下,您需要多个状态机实例。为了解决您的问题,我认为定义两个不同的状态机是更好的方法。它们没有父子关系,但相互发送事件。
假设父状态机作为管理者,子状态机作为工作者。这是两个独立的状态机:
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。
在这种情况下,取消事件从经理发送到工人。并且发现事件从工人发送到经理。
如果你想将workers作为不同的线程运行,你需要使用mutex,如下:
http://melpon.org/wandbox/permlink/TrexYnffiwEpazNk
参见第 100 和 192 行。
Cancel 事件由经理处理并传播给所有工作人员。要测试取消操作,您可以插入取消事件,如下所示:
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;
}