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
//front-end
#include
#include
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 {
typedef int activate_deferred_events;
template
void on_entry(Event const&, FSM&)
{
std::cout << "entering: fsm_master" << std::endl;
}
template
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
void on_entry(Event const&, FSM&) { std::cout << "entering: not_ready"
<< std::endl; }
template
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
void on_entry(Event const&, FSM&) { std::cout << "starting:
live_wait_for_image" << std::endl; }
template
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
void on_entry(Event const&, FSM&) { std::cout << "starting:
live_got_image" << std::endl; }
template
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
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;
}
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;
}