Boost logo

Boost Users :

Subject: [Boost-users] Boost::MSM: Transition Priority
From: georg_at_[hidden]
Date: 2015-03-12 08:49:29


I try to use boost::MSM to implement a simple state machine for testing
purpose. There are several events which have to be processed in the right
order, so i defer the other events, which are currently not allowed. I try
to defer the events in the transition table, to have one place to look for
it, despite having all states to look, what events they defer.

I tried to change the transition rows to change their priorities, but it
didnt help. If i unkomment the anonymous transition from live_got_image to
live_wait_for_image, it works as expected, but i want to transition
automaticly to repeatedly enter the states
live_wait_for_image/live_got_image until the ev_stop_live get sent.

I expect the following output:
------------------------------

        entering: fsm_master
        entering: not_ready
        no transition from state 0 on event struct `anonymous
namespace'::ev_stop_live
        leaving: not_ready
        starting: live_wait_for_image
        leaving: live_wait_for_image
        starting: live_got_image
        leaving: live_got_image
        entering: not_ready

but actually i get the following output:
----------------------------------------

        entering: fsm_master
        entering: not_ready
        no transition from state 0 on event struct `anonymous
namespace'::ev_stop_live
        leaving: not_ready
        starting: live_wait_for_image
        leaving: live_wait_for_image
        starting: live_got_image
        leaving: live_got_image
        starting: live_wait_for_image

I use boost 1.57.0 and MSVC-2013 (VS-12).

Could anybody get me a useful hint?

Georg

Here is the code:

#include <iostream>
// back-end
#include <boost/msm/back/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>

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

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

        // events
        struct ev_start_stop {};
        struct ev_start_live {};
        struct ev_stop_live {};
        struct ev_learn {};
        struct ev_load {};

        struct ev_got_image { int payload; };

        // front end: define the FSM structure
        struct fsm_master_ : public msm::front::state_machine_def<fsm_master_> {
                typedef int activate_deferred_events;

                template <class Event, class FSM>
                void on_entry(Event const&, FSM&)
                {
                        std::cout << "entering: fsm_master" << std::endl;
                }
                template <class Event, class FSM>
                void on_exit(Event const&, FSM&)
                {
                        std::cout << "leaving: fsm_master" << std::endl;
                }

                // the fsm states which are not sub state machines
                struct not_ready : public msm::front::state<> {
                        template <class Event, class FSM>
                        void on_entry(Event const&, FSM&) { std::cout << "entering: not_ready"
<< std::endl; }
                        template <class Event, class FSM>
                        void on_exit(Event const&, FSM&) { std::cout << "leaving: not_ready" <<
std::endl; }
                };

                // The list of FSM states
                struct live_wait_for_image : public msm::front::state<>
                {
                        template <class Event, class FSM>
                        void on_entry(Event const&, FSM&) { std::cout << "starting:
live_wait_for_image" << std::endl; }
                        template <class Event, class FSM>
                        void on_exit(Event const&, FSM&) { std::cout << "leaving:
live_wait_for_image" << std::endl; }
                };

                struct live_got_image : public msm::front::state<>
                {
                        // here we got the image and we can check, if we need to react on an
external event
                        // otherwise transit to wait_for_image and fetch the next image
                        template <class Event, class FSM>
                        void on_entry(Event const&, FSM&) { std::cout << "starting:
live_got_image" << std::endl; }
                        template <class Event, class FSM>
                        void on_exit(Event const&, FSM&) { std::cout << "leaving:
live_got_image" << std::endl; }
                };

                // ---------------------------------------------------
                // initial state: fsm_master_
                typedef not_ready initial_state;

                typedef fsm_master_ l;
                struct transition_table : mpl::vector<
                        // Start Event Next Action
      Guard
                        //
+---------------------+----------------+-------------------+-------------------+----------------+
                        _row < not_ready, ev_start_live, live_wait_for_image
>,

                        _row < live_wait_for_image, ev_got_image, live_got_image
>,
                         Row < live_wait_for_image, ev_stop_live, none ,
Defer , none >,

                        _row < live_got_image, none, live_wait_for_image
>,
                        _row < live_got_image, ev_stop_live, not_ready
>
                        //
+---------------------+----------------+-------------------+-------------------+----------------+
> {};

                // Replaces the default no-transition response.
                template <class FSM, class Event>
                void no_transition(Event const& e, FSM&, int state)
                {
                        std::cout << "no transition from state " << state
                                << " on event " << typeid(e).name() << std::endl;
                }

        };

        // back-end: fsm_master
        typedef msm::back::state_machine<fsm_master_> fsm_master;
}

void test() {
        fsm_master s;
        s.start();

        s.process_event(ev_stop_live()); // this gets no transitioned

        s.process_event(ev_start_live()); // this one enters live
        s.process_event(ev_stop_live()); // this gets defered
        s.process_event(ev_got_image()); // this one enters got_image and the
stop live should get processed.

        // now we should be in not ready again, but we are still in
live_wait_for_image

}
int main()
{
        test();
        return 0;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net