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