Boost.MSM:通过联接伪状态退出正交区域 [英] Boost.MSM: Exit orthogonal regions via a join pseudo state

查看:118
本文介绍了Boost.MSM:通过联接伪状态退出正交区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我打算将<​​strong> boost.msm 与

I intend to use boost.msm with the concept of composite containing orthogonal regions. I want to synchronize all orthogonal regions upon exit. In other words: the state following my composite shall be activated if and only if all regions have reached their last state.

UML 2.4上层建筑" 建议 加入 伪状态(即第15.3.8节).在boost中,有一个 fork ,但是我找不到对应的join的任何实现.

UML 2.4 "Superstructure" proposes join pseudo states (i.e. chapter 15.3.8). In boost, there is a fork but I cannot find any implementation of its counterpart join.

boost.msm中是否没有连接伪状态?我将如何在boost.msm中应用加入伪状态的概念?

推荐答案

您可以使用一个计数器,该计数器在每次进入连接状态时都会增加.当此计数器等于正交区域数时,将激活联接状态之后的状态.

You could use a counter which will increment each time the join state is entered. When this counter equals the number of orthogonal regions, the state following the join state will be activated.

这可以手动完成,也可以通过一般方式完成. 下面,我实现了一种通用方法,其中通过从模板JoinSM继承,将联接逻辑添加到子计算机Sub中.

This could be done manually or in a generic way. Below I implemented a generic way where the joining logic is added to the submachine Sub by inheriting from the template JoinSM.

Sub具有3个正交区域(在此简单示例中,每个区域仅包含一个状态,即Orthogonal1Orthogonal2Orthogonal3).所有这些正交状态都连接到Join状态,但是在Sub中未指定从Join状态直接连接到Exit状态.

Sub has 3 orthogonal regions (which in this simple example just consist of one state each, namely Orthogonal1, Orthogonal2 and Orthogonal3). All of these orthogonal states are connected to the Join state but no direct connection to the Exit state from the Join state is specified within Sub.

此连接在JoinSM中实现.每次从Sub进入Join状态时,都会激活Waiting状态并使计数器递增.如果计数器达到正交区域数,则触发事件AllJoined并激活到Exit的过渡.

This connection is implemented in JoinSM. Every time the Join state is reached from Sub, the Waiting state is activated and the counter is incremented. If the counter reaches the number of orthogonal regions, the Event AllJoined is fired and the transition to Exit is activated.

由于JoinSM通过initial_state的大小查询正交区域的数量,因此在Sub中添加或删除区域将自动反映在连接逻辑中.

Since JoinSM queries the number of orthogonal regions through the size of initial_state, adding or removing regions in Sub will automatically be reflected in the joining logic.

#include <iostream>
#include <cstdlib>
#include <memory>
#include <cxxabi.h>

template <class T>
std::string demangle()
{
    const char* name = typeid(T).name();
    int status = -1; 
    std::unique_ptr<char, void(*)(void*)> res {
        abi::__cxa_demangle(name, NULL, NULL, &status),
        std::free
    };
    return (status==0) ? res.get() : name ;
}


#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/back/metafunctions.hpp>
#include <boost/mpl/assert.hpp>

using namespace boost::msm;
using namespace boost::msm::front;


template <typename State>
struct BaseState : public boost::msm::front::state<>
{
    template <class Event,class FSM> void on_entry(Event const&,FSM& )
    {
        std::cout << "on_entry: " << demangle<State>()  << std::endl;
    }
    template <class Event,class FSM> void on_exit(Event const&,FSM& ) 
    {
        std::cout << "on_exit: " << demangle<State>() << std::endl;
    }
};


// EVENTS
struct EnterOrthogonal {};

struct Orthogonal1Finished{};
struct Orthogonal2Finished{};
struct Orthogonal3Finished{};



struct SubSM_ : state_machine_def<SubSM_>
{
    struct Started : BaseState<Started>{};
    struct Exit : exit_pseudo_state<none> {};

    struct Orthogonal1 : BaseState<Orthogonal1>{};
    struct Orthogonal2 : BaseState<Orthogonal2>{};
    struct Orthogonal3 : BaseState<Orthogonal3>{};

    struct Join : BaseState<Join>{};

    typedef boost::mpl::vector<Orthogonal1, Orthogonal2, Orthogonal3> initial_state;
    struct transition_table : boost::mpl::vector<
     Row<Orthogonal1, Orthogonal1Finished, Join, none, none>,
     Row<Orthogonal2, Orthogonal2Finished, Join, none, none>,
     Row<Orthogonal3, Orthogonal3Finished, Join, none, none>
     > {};
};


template <typename SM, typename JoinState = typename SM::Join, typename ExitState = typename SM::Exit>
struct JoinSM  : SM
{
    struct AllJoined{};

    constexpr static int num_regions = boost::mpl::size<typename SM::initial_state>::value;
    int count;

    template <class Event,class FSM>
    void on_entry(Event const& ,FSM&) 
    {
        // reset count
        count = 0;
    }

    struct Waiting : BaseState<Waiting>
    {
        template <class Event,class FSM>
        void on_entry(const Event& e,FSM& f)
        {
            BaseState<Waiting>::on_entry(e,f);
            f.count++; 
            if (f.count == FSM::num_regions)
            {
                f.process_event(AllJoined()); 
            } 
        }
    };

    typedef boost::mpl::vector<
        Row<JoinState, none, Waiting, none, none>,
        Row<Waiting, AllJoined, ExitState, none, none>
    > additional_transition_table;

    typedef boost::mpl::joint_view<
        typename SM::transition_table,
        additional_transition_table
    > transition_table;
};

// inherit from JoinSM to add the joining logic
using Sub = back::state_machine<JoinSM<SubSM_>>;

struct MainSM_ : state_machine_def<MainSM_>
{
    struct Started : BaseState<Started>{};
    struct AfterJoin : BaseState<AfterJoin>{};
    using initial_state = boost::mpl::vector<Started>;
    struct transition_table : boost::mpl::vector<
        Row<Started, EnterOrthogonal, Sub, none, none>,
        Row<Sub::exit_pt<SubSM_::Exit>, none, AfterJoin, none, none>
    > {};
};

struct MainSM_;
using Main = back::state_machine<MainSM_>;    


int main()
{

    Main main;
    main.start();
    main.process_event(EnterOrthogonal());
    main.process_event(Orthogonal3Finished());
    main.process_event(Orthogonal1Finished());
    main.process_event(Orthogonal2Finished());
}

输出:

on_entry: MainSM_::Started
on_exit: MainSM_::Started
on_entry: SubSM_::Orthogonal1
on_entry: SubSM_::Orthogonal2
on_entry: SubSM_::Orthogonal3
on_exit: SubSM_::Orthogonal3
on_entry: SubSM_::Join
on_exit: SubSM_::Join
on_entry: JoinSM<SubSM_, SubSM_::Join, SubSM_::Exit>::Waiting
on_exit: SubSM_::Orthogonal1
on_entry: SubSM_::Join
on_exit: SubSM_::Join
on_entry: JoinSM<SubSM_, SubSM_::Join, SubSM_::Exit>::Waiting
on_exit: SubSM_::Orthogonal2
on_entry: SubSM_::Join
on_exit: SubSM_::Join
on_entry: JoinSM<SubSM_, SubSM_::Join, SubSM_::Exit>::Waiting
on_exit: JoinSM<SubSM_, SubSM_::Join, SubSM_::Exit>::Waiting
on_exit: JoinSM<SubSM_, SubSM_::Join, SubSM_::Exit>::Waiting
on_exit: JoinSM<SubSM_, SubSM_::Join, SubSM_::Exit>::Waiting
on_entry: MainSM_::AfterJoin

实时示例: http://coliru.stacked-crooked. com/a/6c060d032bc53573

这篇关于Boost.MSM:通过联接伪状态退出正交区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆