2

私は単純なステート マシンを持っています。3 種類のメッセージを受信し、メッセージの種類に応じて対応する応答を送信します。正しいメッセージが正しい順序で受信される通常の状況では、ステート マシンは完璧に機能します。


ただし、予期しないメッセージが受信された場合は、no_transitionが呼び出され、 error_detectedイベントを発生させる必要があり、normal_workflow状態によって処理する必要があります。ただしno_transition、2 つの直交領域があるため、2 回呼び出されます。しかし、状態の場合にのみ発火error_detectedイベントが必要normal_workflowです。では、現在のアクティブな状態をどのように判断するのno_trasitionですか? ここに私のコードがあります、

#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 <boost/msm/front/euml/common.hpp>

#include <boost/msm/front/euml/operator.hpp>
#include <boost/msm/front/euml/state_grammar.hpp>

namespace msm = boost::msm;
namespace mpl = boost::mpl;

using namespace msm::front;
using namespace msm::front::euml;

namespace
{
    // events
    //
    struct received_type_1_msg { received_type_1_msg(){ std::cout << "received_type_1_msg" << std::endl; } };

    struct received_type_2_msg { received_type_2_msg(){ std::cout << "received_type_2_msg" << std::endl; } };

    struct received_type_3_msg { received_type_3_msg(){ std::cout << "received_type_3_msg" << std::endl; } };

    struct err_detected { err_detected(){ std::cout << "err_detected" << std::endl; } };

    // front end
    //
    struct test_sm_ : public msm::front::state_machine_def<test_sm_>
    {
        // states
        //
        struct idle : public msm::front::state<> 
        {
            template <class event,class fsm>
            void on_entry(event const& evt,fsm& sm) 
            {
                std::cout << "idle" << std::endl;
            }
        };

        struct wait_type_2_msg : public msm::front::state<> 
        {
            template <class event,class fsm>
            void on_entry(event const& evt,fsm& sm) 
            {
                std::cout << "wait_type_1_msg"<< std::endl;
            }
        };

        struct wait_type_3_msg : public msm::front::state<> 
        {
            template <class event,class fsm>
            void on_entry(event const& evt,fsm& sm) 
            {
                std::cout << "wait_type_3_msg"<< std::endl;
            }
        };

        struct normal_workflow : public msm::front::state<> 
        {
            template <class event,class fsm>
            void on_entry(event const& evt,fsm& sm) 
            {
                std::cout << "normal_workflow"<< std::endl;
            }
        };      

        // initial state
        //
        typedef mpl::vector2<idle, normal_workflow> initial_state;

        // transition actions
        //
        struct send_type_1_rsp
        {
            template<class event, class fsm, class src_state, class dst_state>
            void operator()(event const& evt, fsm&, src_state&, dst_state&) 
            {
                std::cout << "send_type_1_rsp"<< std::endl;
            }
        };

        struct send_type_2_rsp
        {
            template<class event, class fsm, class src_state, class dst_state>
            void operator()(event const& evt, fsm&, src_state&, dst_state&) 
            {
                std::cout << "send_type_2_rsp"<< std::endl;
            }
        };

        struct send_type_3_rsp
        {
            template<class event, class fsm, class src_state, class dst_state>
            void operator()(event const& evt, fsm&, src_state&, dst_state&) 
            {
                std::cout << "send_type_3_rsp"<< std::endl;
            }
        };

        struct send_error_rsp
        {
            template<class event, class fsm, class src_state, class dst_state>
            void operator()(event const& evt, fsm&, src_state&, dst_state&) 
            {
                std::cout << "send_error_rsp"<< std::endl;
            }
        };

        struct transition_table : mpl::vector<

            //     Start                       Event                           Next                        Action                         Guard
            //    +---------------------------+-------------------------------+---------------------------+------------------------------+--------+
            Row   < idle                      , received_type_1_msg           , wait_type_2_msg           , send_type_1_rsp              , none   >,
            Row   < wait_type_2_msg           , received_type_2_msg           , wait_type_3_msg           , send_type_2_rsp              , none   >,
            Row   < wait_type_3_msg           , received_type_3_msg           , idle                      , send_type_3_rsp              , none   >,
            //    +---------------------------+-------------------------------+---------------------------+------------------------------+--------+
            Row   < normal_workflow           , err_detected                  , idle                      , send_error_rsp               , none   >
            //    +---------------------------+-------------------------------+---------------------------+------------------------------+--------+
        >{};

        // no transition
        //
        template <class fsm,class event>
        void no_transition(event const& e, fsm& sm,int state)
        {
            std::cout << "no transition" << std::endl;
            //sm.process_event(err_detected());
        }
    };

    typedef msm::back::state_machine<test_sm_> test_sm;
}

int main(int argc, char** argv) 
{
    test_sm sm;
    sm.start();

    sm.process_event(received_type_1_msg());
    sm.process_event(received_type_2_msg());

    // wrong message received
    //
    sm.process_event(received_type_2_msg());

    return 0;
}

1 つの解決策は、 に渡される状態引数を使用することno_transitionです。他の解決策はありますか?このようなものは見栄えがよくないため:

template <class fsm,class event>
void no_transition(event const& e, fsm& sm,int state)
{
    // without this condition err_detected event will fired twise, because sm have 2 regions
    //
    if(state == 3)
    {
        // call this event only in NORMAL_WORKFLOW state, because it handled within this state
        //
        sm.process_event(err_detected());
    }
}
4

1 に答える 1

1

まあ、私見、直交領域の使用法は良いです。ただし、エラー処理イベントは自分で起動する必要があります。no_transition は、MSM がうまくいかないときの唯一の機能です。だから、私はあなたと同じようにやっています。

于 2012-05-14T05:43:55.920 に答える