• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2010 Christophe Henry
2 // henry UNDERSCORE christophe AT hotmail DOT com
3 // This is an extended version of the state machine available in the boost::mpl library
4 // Distributed under the same license as the original.
5 // Copyright for the original version:
6 // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
7 // under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 
11 #include <iostream>
12 // back-end
13 #include <boost/msm/back/state_machine.hpp>
14 #include <boost/msm/front/euml/euml.hpp>
15 
16 namespace msm = boost::msm;
17 using namespace boost::msm::front::euml;
18 
19 namespace
20 {
21     // events
22     BOOST_MSM_EUML_EVENT(event1)
23 
BOOST_MSM_EUML_ACTION(State1_Entry)24     BOOST_MSM_EUML_ACTION(State1_Entry)
25     {
26         template <class Event,class FSM,class STATE>
27         void operator()(Event const&,FSM&,STATE& )
28         {
29             std::cout << "entering: State1" << std::endl;
30         }
31     };
BOOST_MSM_EUML_ACTION(State1_Exit)32     BOOST_MSM_EUML_ACTION(State1_Exit)
33     {
34         template <class Event,class FSM,class STATE>
35         void operator()(Event const&,FSM&,STATE& )
36         {
37             std::cout << "leaving: State1" << std::endl;
38         }
39     };
BOOST_MSM_EUML_ACTION(State2_Entry)40     BOOST_MSM_EUML_ACTION(State2_Entry)
41     {
42         template <class Event,class FSM,class STATE>
43         void operator()(Event const&,FSM&,STATE& )
44         {
45             std::cout << "entering: State2" << std::endl;
46         }
47     };
BOOST_MSM_EUML_ACTION(State2_Exit)48     BOOST_MSM_EUML_ACTION(State2_Exit)
49     {
50         template <class Event,class FSM,class STATE>
51         void operator()(Event const&,FSM&,STATE& )
52         {
53             std::cout << "leaving: State2" << std::endl;
54         }
55     };
BOOST_MSM_EUML_ACTION(State3_Entry)56     BOOST_MSM_EUML_ACTION(State3_Entry)
57     {
58         template <class Event,class FSM,class STATE>
59         void operator()(Event const&,FSM&,STATE& )
60         {
61             std::cout << "entering: State3" << std::endl;
62         }
63     };
BOOST_MSM_EUML_ACTION(State3_Exit)64     BOOST_MSM_EUML_ACTION(State3_Exit)
65     {
66         template <class Event,class FSM,class STATE>
67         void operator()(Event const&,FSM&,STATE& )
68         {
69             std::cout << "leaving: State3" << std::endl;
70         }
71     };
BOOST_MSM_EUML_ACTION(State4_Entry)72     BOOST_MSM_EUML_ACTION(State4_Entry)
73     {
74         template <class Event,class FSM,class STATE>
75         void operator()(Event const&,FSM&,STATE& )
76         {
77             std::cout << "entering: State4" << std::endl;
78         }
79     };
BOOST_MSM_EUML_ACTION(State4_Exit)80     BOOST_MSM_EUML_ACTION(State4_Exit)
81     {
82         template <class Event,class FSM,class STATE>
83         void operator()(Event const&,FSM&,STATE& )
84         {
85             std::cout << "leaving: State4" << std::endl;
86         }
87     };
88 
89     // The list of FSM states
90     BOOST_MSM_EUML_STATE(( State1_Entry,State1_Exit ),State1)
91     BOOST_MSM_EUML_STATE(( State2_Entry,State2_Exit ),State2)
92     BOOST_MSM_EUML_STATE(( State3_Entry,State3_Exit ),State3)
93     BOOST_MSM_EUML_STATE(( State4_Entry,State4_Exit ),State4)
94 
95     // transition actions
BOOST_MSM_EUML_ACTION(State2ToState3)96     BOOST_MSM_EUML_ACTION(State2ToState3)
97     {
98         template <class FSM,class EVT,class SourceState,class TargetState>
99         void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
100         {
101             std::cout << "my_machine::State2ToState3" << std::endl;
102         }
103     };
BOOST_MSM_EUML_ACTION(State3ToState4)104     BOOST_MSM_EUML_ACTION(State3ToState4)
105     {
106         template <class FSM,class EVT,class SourceState,class TargetState>
107         void operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
108         {
109             std::cout << "my_machine::State3ToState4" << std::endl;
110         }
111     };
112     // guard conditions
BOOST_MSM_EUML_ACTION(always_true)113     BOOST_MSM_EUML_ACTION(always_true)
114     {
115         template <class FSM,class EVT,class SourceState,class TargetState>
116         bool operator()(EVT const& evt,FSM&,SourceState& ,TargetState& )
117         {
118             std::cout << "always_true" << std::endl;
119             return true;
120         }
121     };
BOOST_MSM_EUML_ACTION(always_false)122     BOOST_MSM_EUML_ACTION(always_false)
123     {
124         template <class FSM,class EVT,class SourceState,class TargetState>
125         bool operator()(EVT const& evt,FSM&,SourceState& ,TargetState& )
126         {
127             std::cout << "always_false" << std::endl;
128             return false;
129         }
130     };
131     // replaces the old transition table
132     BOOST_MSM_EUML_TRANSITION_TABLE((
133           State2      == State1  ,
134           State3      == State2 / State2ToState3,
135           State4      == State3 [always_true] / State3ToState4,
136           State4      == State3 [always_false],
137           State1      == State4 + event1
138           //  +------------------------------------------------------------------------------+
139           ),transition_table)
140 
141     // create a state machine "on the fly"
142     BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
143                                         init_ << State1  // Init State
144                                         ),
145                                       my_machine_) //fsm name
146 
147     // Pick a back-end
148     typedef msm::back::state_machine<my_machine_> my_machine;
149 
150     //
151     // Testing utilities.
152     //
153     static char const* const state_names[] = { "State1", "State2", "State3", "State4" };
pstate(my_machine const & p)154     void pstate(my_machine const& p)
155     {
156         std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
157     }
158 
test()159     void test()
160     {
161         my_machine p;
162 
163         // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
164         // in this case it will also immediately trigger all anonymous transitions
165         p.start();
166         // this event will bring us back to the initial state and thus, a new "loop" will be started
167         p.process_event(event1);
168     }
169 }
170 
main()171 int main()
172 {
173     test();
174     return 0;
175 }
176