【发布时间】:2018-06-04 10:55:31
【问题描述】:
我正在尝试使用 boost::msm 实现一个简单的协议。当数据包到达时,它们会被处理并分派到状态机 (SM) 进行相应处理。
我的 pkt 类(即 Pkt1)需要一个 fsm 句柄,以允许它调用 fsm->process_event(...)(当然我会在 pkt1.h 的顶部添加 #include "myfsm.h")。
到目前为止一切顺利。但是,如果我的状态机(比如 State1)需要通过发送数据包本身来对该数据包做出反应怎么办?现在我将在“state1.h”的顶部包含“pkt1.h”标头,这样我就可以创建 Pkt1 的一个实例并调用它的 send() 函数。
正如您可能猜到的那样,最终包含会导致“循环依赖”
示例代码(有错误)可以找到:https://wandbox.org/permlink/IlFsUQyLPLrLl2RW(这是我第一次使用wandbox,希望一切正常)
注意)在“state1.h”文件中删除#include "pkt1.h"和on_entry(..)... Pkt1 pkt; pkt.send();使其可编译。
问题:
1) 我应该如何解决这种循环依赖?
2) 我认为前进的方向是为我的 Pkt1 类添加一个实现文件 (.cpp) 并将#include "myfsm.h" 传输到该文件,从而打破循环依赖。但是如何在头文件中转发声明MyFsm?
3) 我是 boost::msm/CRTP 的新手,代码让我很困惑。 State1 如何访问MyFsm 而我没有在 state1.h 中包含相应的标头? (可能是因为MyFsm 源自包含其标头的函子前端/后端,并允许虚函数调用相应的 MyFsm 函数!!??)
非常感谢您提前抽出时间和帮助。
包含的代码:
-
events.h
#ifndef EVENTS #define EVENTS // ----- Events struct Event1 {}; struct Event2 {}; #endif // EVENTS -
main.cpp
#include <iostream> #include "events.h" #include "myfsm.h" #include "pkt1.h" int main() { MyFsm fsm; fsm.start(); //fsm.process_event(Event1()); Pkt1 rcvdPkt; rcvdPkt.dispatch(&fsm); return 0; } -
myfsm.h
//MyFsm.h #ifndef MYFSM #define MYFSM #include <iostream> #include <boost/msm/back/state_machine.hpp> #include <boost/msm/front/state_machine_def.hpp> #include <boost/msm/front/functor_row.hpp> #include "state1.h" #include "state2.h" #include "events.h" namespace msm = boost::msm; namespace msmf = boost::msm::front; namespace mpl = boost::mpl; struct MyFsm_ : msmf::state_machine_def<MyFsm_> { struct State1_ : State1 {}; // use public inheritance struct State2_ : State2 {}; // use public inheritance // Set initial state typedef State1_ initial_state; // Transition table struct transition_table:mpl::vector< msmf::Row < State1_, Event1, State2_, msmf::none, msmf::none > >{}; }; // Pick a back-end typedef msm::back::state_machine<MyFsm_> MyFsm; #endif // MYFSM -
pkt1.h
#ifndef PKT1 #define PKT1 #include "myfsm.h" #include "events.h" class Pkt1 { public: Pkt1() {} void dispatch(MyFsm *fsm){ fsm->process_event(Event1()); } void send(){std::cout<<"pkt1 sent out ..."<<std::endl;} }; #endif // PKT1 -
state1.h
//State1.h #ifndef STATE1 #define STATE1 #include <iostream> #include <boost/msm/back/state_machine.hpp> #include <boost/msm/front/state_machine_def.hpp> #include <boost/msm/front/functor_row.hpp> #include "pkt1.h" //comment this line to resolve the compliation error 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; Pkt1 pkt; pkt.send();//comment this line to resolve the compliation error } // Exit action template <class Event,class Fsm> void on_exit(Event const&, Fsm&) const { std::cout << "State1::on_exit()" << std::endl; } }; #endif // STATE1 -
state2.h
//State2.h #ifndef STATE2 #define STATE2 #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 State2:msmf::state<> { // Entry action template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "State2::on_entry()" << std::endl; } // Exit action template <class Event,class Fsm> void on_exit(Event const&, Fsm&) const { std::cout << "State2::on_exit()" << std::endl; } }; #endif // STATE2
【问题讨论】:
标签: c++ boost template-meta-programming code-separation boost-msm