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 <vector>
12 #include <iostream>
13
14 #include <boost/msm/back/state_machine.hpp>
15 #include <boost/msm/front/euml/euml.hpp>
16
17 using namespace std;
18 using namespace boost::msm::front::euml;
19 namespace msm = boost::msm;
20 namespace mpl = boost::mpl;
21
22
23 namespace // Concrete FSM implementation
24 {
25 // events
26 BOOST_MSM_EUML_EVENT(event1)
27 BOOST_MSM_EUML_EVENT(event2)
28 BOOST_MSM_EUML_EVENT(event3)
29 BOOST_MSM_EUML_EVENT(event4)
30 BOOST_MSM_EUML_EVENT(event5)
31 // if we need something special, like a template constructor, we cannot use the helper macros
32 struct event6_impl : euml_event<event6_impl>
33 {
event6_impl__anon6c42131a0111::event6_impl34 event6_impl(){}
35 template <class Event>
event6_impl__anon6c42131a0111::event6_impl36 event6_impl(Event const&){}
37 };
38 event6_impl const event6;
39
40 //Sub fsm state definition
BOOST_MSM_EUML_ACTION(SubState1_Entry)41 BOOST_MSM_EUML_ACTION(SubState1_Entry)
42 {
43 template <class Event,class FSM,class STATE>
44 void operator()(Event const&,FSM&,STATE& )
45 {
46 std::cout << "entering: SubFsm2::SubState1" << std::endl;
47 }
48 };
BOOST_MSM_EUML_ACTION(SubState1_Exit)49 BOOST_MSM_EUML_ACTION(SubState1_Exit)
50 {
51 template <class Event,class FSM,class STATE>
52 void operator()(Event const&,FSM&,STATE& )
53 {
54 std::cout << "leaving: SubFsm2::SubState1" << std::endl;
55 }
56 };
57 BOOST_MSM_EUML_STATE(( SubState1_Entry,SubState1_Exit ),SubState1)
58
BOOST_MSM_EUML_ACTION(SubState1b_Entry)59 BOOST_MSM_EUML_ACTION(SubState1b_Entry)
60 {
61 template <class Event,class FSM,class STATE>
62 void operator()(Event const&,FSM&,STATE& )
63 {
64 std::cout << "entering: SubFsm2::SubState1b" << std::endl;
65 }
66 };
BOOST_MSM_EUML_ACTION(SubState1b_Exit)67 BOOST_MSM_EUML_ACTION(SubState1b_Exit)
68 {
69 template <class Event,class FSM,class STATE>
70 void operator()(Event const&,FSM&,STATE& )
71 {
72 std::cout << "leaving: SubFsm2::SubState1b" << std::endl;
73 }
74 };
75 BOOST_MSM_EUML_STATE(( SubState1b_Entry,SubState1b_Exit ),SubState1b)
76
BOOST_MSM_EUML_ACTION(SubState1c_Entry)77 BOOST_MSM_EUML_ACTION(SubState1c_Entry)
78 {
79 template <class Event,class FSM,class STATE>
80 void operator()(Event const&,FSM&,STATE& )
81 {
82 std::cout << "entering: SubFsm2::SubState1c" << std::endl;
83 }
84 };
BOOST_MSM_EUML_ACTION(SubState1c_Exit)85 BOOST_MSM_EUML_ACTION(SubState1c_Exit)
86 {
87 template <class Event,class FSM,class STATE>
88 void operator()(Event const&,FSM&,STATE& )
89 {
90 std::cout << "leaving: SubFsm2::SubState1c" << std::endl;
91 }
92 };
93 BOOST_MSM_EUML_STATE(( SubState1c_Entry,SubState1c_Exit ),SubState1c)
94
BOOST_MSM_EUML_ACTION(SubState2_Entry)95 BOOST_MSM_EUML_ACTION(SubState2_Entry)
96 {
97 template <class Event,class FSM,class STATE>
98 void operator()(Event const&,FSM&,STATE& )
99 {
100 std::cout << "entering: SubFsm2::SubState2" << std::endl;
101 }
102 };
BOOST_MSM_EUML_ACTION(SubState2_Exit)103 BOOST_MSM_EUML_ACTION(SubState2_Exit)
104 {
105 template <class Event,class FSM,class STATE>
106 void operator()(Event const&,FSM&,STATE& )
107 {
108 std::cout << "leaving: SubFsm2::SubState2" << std::endl;
109 }
110 };
111 BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE(0,( SubState2_Entry,SubState2_Exit ),SubState2)
112
BOOST_MSM_EUML_ACTION(SubState2b_Entry)113 BOOST_MSM_EUML_ACTION(SubState2b_Entry)
114 {
115 template <class Event,class FSM,class STATE>
116 void operator()(Event const&,FSM&,STATE& )
117 {
118 std::cout << "entering: SubFsm2::SubState2b" << std::endl;
119 }
120 };
BOOST_MSM_EUML_ACTION(SubState2b_Exit)121 BOOST_MSM_EUML_ACTION(SubState2b_Exit)
122 {
123 template <class Event,class FSM,class STATE>
124 void operator()(Event const&,FSM&,STATE& )
125 {
126 std::cout << "leaving: SubFsm2::SubState2b" << std::endl;
127 }
128 };
129 BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE(1,( SubState2b_Entry,SubState2b_Exit ),SubState2b)
130
BOOST_MSM_EUML_ACTION(SubState2c_Entry)131 BOOST_MSM_EUML_ACTION(SubState2c_Entry)
132 {
133 template <class Event,class FSM,class STATE>
134 void operator()(Event const&,FSM&,STATE& )
135 {
136 std::cout << "entering: SubFsm2::SubState2c" << std::endl;
137 }
138 };
BOOST_MSM_EUML_ACTION(SubState2c_Exit)139 BOOST_MSM_EUML_ACTION(SubState2c_Exit)
140 {
141 template <class Event,class FSM,class STATE>
142 void operator()(Event const&,FSM&,STATE& )
143 {
144 std::cout << "leaving: SubFsm2::SubState2c" << std::endl;
145 }
146 };
147 BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE(2,( SubState2c_Entry,SubState2c_Exit ),SubState2c)
148
BOOST_MSM_EUML_ACTION(PseudoEntry1_Entry)149 BOOST_MSM_EUML_ACTION(PseudoEntry1_Entry)
150 {
151 template <class Event,class FSM,class STATE>
152 void operator()(Event const&,FSM&,STATE& )
153 {
154 std::cout << "entering: SubFsm2::PseudoEntry1" << std::endl;
155 }
156 };
BOOST_MSM_EUML_ACTION(PseudoEntry1_Exit)157 BOOST_MSM_EUML_ACTION(PseudoEntry1_Exit)
158 {
159 template <class Event,class FSM,class STATE>
160 void operator()(Event const&,FSM&,STATE& )
161 {
162 std::cout << "leaving: SubFsm2::PseudoEntry1" << std::endl;
163 }
164 };
165 BOOST_MSM_EUML_ENTRY_STATE(0,( PseudoEntry1_Entry,PseudoEntry1_Exit ),PseudoEntry1)
166
BOOST_MSM_EUML_ACTION(SubState3_Entry)167 BOOST_MSM_EUML_ACTION(SubState3_Entry)
168 {
169 template <class Event,class FSM,class STATE>
170 void operator()(Event const&,FSM&,STATE& )
171 {
172 std::cout << "entering: SubFsm2::SubState3" << std::endl;
173 }
174 };
BOOST_MSM_EUML_ACTION(SubState3_Exit)175 BOOST_MSM_EUML_ACTION(SubState3_Exit)
176 {
177 template <class Event,class FSM,class STATE>
178 void operator()(Event const&,FSM&,STATE& )
179 {
180 std::cout << "leaving: SubFsm2::SubState3" << std::endl;
181 }
182 };
183 BOOST_MSM_EUML_STATE(( SubState3_Entry,SubState3_Exit ),SubState3)
184
BOOST_MSM_EUML_ACTION(SubState3b_Entry)185 BOOST_MSM_EUML_ACTION(SubState3b_Entry)
186 {
187 template <class Event,class FSM,class STATE>
188 void operator()(Event const&,FSM&,STATE& )
189 {
190 std::cout << "entering: SubFsm2::SubState3b" << std::endl;
191 }
192 };
BOOST_MSM_EUML_ACTION(SubState3b_Exit)193 BOOST_MSM_EUML_ACTION(SubState3b_Exit)
194 {
195 template <class Event,class FSM,class STATE>
196 void operator()(Event const&,FSM&,STATE& )
197 {
198 std::cout << "leaving: SubFsm2::SubState3b" << std::endl;
199 }
200 };
201 BOOST_MSM_EUML_STATE(( SubState3b_Entry,SubState3b_Exit ),SubState3b)
202
BOOST_MSM_EUML_ACTION(PseudoExit1_Entry)203 BOOST_MSM_EUML_ACTION(PseudoExit1_Entry)
204 {
205 template <class Event,class FSM,class STATE>
206 void operator()(Event const&,FSM&,STATE& )
207 {
208 std::cout << "entering: SubFsm2::PseudoExit1" << std::endl;
209 }
210 };
BOOST_MSM_EUML_ACTION(PseudoExit1_Exit)211 BOOST_MSM_EUML_ACTION(PseudoExit1_Exit)
212 {
213 template <class Event,class FSM,class STATE>
214 void operator()(Event const&,FSM&,STATE& )
215 {
216 std::cout << "leaving: SubFsm2::PseudoExit1" << std::endl;
217 }
218 };
219 BOOST_MSM_EUML_EXIT_STATE(( event6,PseudoExit1_Entry,PseudoExit1_Exit ),PseudoExit1)
220
221 // actions
BOOST_MSM_EUML_ACTION(entry_action)222 BOOST_MSM_EUML_ACTION(entry_action)
223 {
224 template <class FSM,class EVT,class SourceState,class TargetState>
225 void operator()(FSM& ,EVT const& ,SourceState& ,TargetState& )
226 {
227 cout << "calling entry_action" << endl;
228 }
229 };
230 // SubFsm definition
BOOST_MSM_EUML_ACTION(SubFsm2_Entry)231 BOOST_MSM_EUML_ACTION(SubFsm2_Entry)
232 {
233 template <class Event,class FSM,class STATE>
234 void operator()(Event const&,FSM&,STATE& )
235 {
236 std::cout << "entering: SubFsm2" << std::endl;
237 }
238 };
BOOST_MSM_EUML_ACTION(SubFsm2_Exit)239 BOOST_MSM_EUML_ACTION(SubFsm2_Exit)
240 {
241 template <class Event,class FSM,class STATE>
242 void operator()(Event const&,FSM&,STATE& )
243 {
244 std::cout << "leaving: SubFsm2" << std::endl;
245 }
246 };
247 BOOST_MSM_EUML_TRANSITION_TABLE((
248 // +------------------------------------------------------------------------------+
249 SubState3 == PseudoEntry1 + event4 / entry_action ,
250 SubState1 == SubState2 + event6 ,
251 PseudoExit1 == SubState3 + event5
252 // +------------------------------------------------------------------------------+
253 ), SubFsm2_transition_table)
254
255 BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (SubFsm2_transition_table, //STT
256 init_ << SubState1 << SubState1b << SubState1c, // Init State
257 SubFsm2_Entry, // Entry
258 SubFsm2_Exit
259 ),SubFsm2_def)
260 // inherit to add some typedef
261 struct SubFsm2_ : public SubFsm2_def
262 {
263 // these 2 states are not found in the transition table because they are accessed only through
264 // a fork, so we need to create them explicitly
265 typedef mpl::vector<BOOST_MSM_EUML_STATE_NAME(SubState2b),
266 BOOST_MSM_EUML_STATE_NAME(SubState2c)> explicit_creation;
267 };
268
269 // back-end
270 typedef msm::back::state_machine<SubFsm2_> SubFsm2_type;
271 SubFsm2_type const SubFsm2;
272
273 // Fsm state definitions
BOOST_MSM_EUML_ACTION(State1_Entry)274 BOOST_MSM_EUML_ACTION(State1_Entry)
275 {
276 template <class Event,class FSM,class STATE>
277 void operator()(Event const&,FSM&,STATE& )
278 {
279 std::cout << "entering: State1" << std::endl;
280 }
281 };
BOOST_MSM_EUML_ACTION(State1_Exit)282 BOOST_MSM_EUML_ACTION(State1_Exit)
283 {
284 template <class Event,class FSM,class STATE>
285 void operator()(Event const&,FSM&,STATE& )
286 {
287 std::cout << "leaving: State1" << std::endl;
288 }
289 };
290 BOOST_MSM_EUML_STATE(( State1_Entry,State1_Exit ),State1)
291
BOOST_MSM_EUML_ACTION(State2_Entry)292 BOOST_MSM_EUML_ACTION(State2_Entry)
293 {
294 template <class Event,class FSM,class STATE>
295 void operator()(Event const&,FSM&,STATE& )
296 {
297 std::cout << "entering: State2" << std::endl;
298 }
299 };
BOOST_MSM_EUML_ACTION(State2_Exit)300 BOOST_MSM_EUML_ACTION(State2_Exit)
301 {
302 template <class Event,class FSM,class STATE>
303 void operator()(Event const&,FSM&,STATE& )
304 {
305 std::cout << "leaving: State2" << std::endl;
306 }
307 };
308 BOOST_MSM_EUML_STATE(( State2_Entry,State2_Exit ),State2)
309
310 // Fsm definition
311 BOOST_MSM_EUML_TRANSITION_TABLE((
312 // +------------------------------------------------------------------------------+
313 SubFsm2 == State1 + event1 ,
314 explicit_(SubFsm2,SubState2) == State1 + event2,
315 (explicit_(SubFsm2,SubState2),
316 explicit_(SubFsm2,SubState2b),
317 explicit_(SubFsm2,SubState2c)) == State1 + event3 ,
318 entry_pt_(SubFsm2,PseudoEntry1) == State1 + event4 ,
319 State1 == SubFsm2 + event1 ,
320 State2 == exit_pt_
321 (SubFsm2,PseudoExit1) + event6
322 // +------------------------------------------------------------------------------+
323 ),transition_table )
324
325
BOOST_MSM_EUML_ACTION(Log_No_Transition)326 BOOST_MSM_EUML_ACTION(Log_No_Transition)
327 {
328 template <class Event,class FSM,class STATE>
329 void operator()(Event const& e,FSM&,STATE& )
330 {
331 std::cout << "no transition in Fsm"
332 << " on event " << typeid(e).name() << std::endl;
333 }
334 };
335 BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
336 init_ << State1, // Init State
337 no_action, // Entry
338 no_action, // Exit
339 attributes_ << no_attributes_, // Attributes
340 configure_ << no_configure_, // configuration
341 Log_No_Transition // no_transition handler
342 ),
343 Fsm_) //fsm name
344
345 //back-end
346 typedef msm::back::state_machine<Fsm_> Fsm;
347
348 //
349 // Testing utilities.
350 //
351 static char const* const state_names[] = { "State1", "SubFsm2","State2" };
pstate(Fsm const & p)352 void pstate(Fsm const& p)
353 {
354 std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
355 }
356
test()357 void test()
358 {
359 Fsm p;
360 // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
361 p.start();
362 std::cout << "Simply move in and out of the composite, activate init states" << std::endl;
363 p.process_event(event1); pstate(p);
364 p.process_event(event1); pstate(p);
365 std::cout << "Direct entry into SubFsm2::SubState2, then transition to SubState1 and back to State1" << std::endl;
366 p.process_event(event2); pstate(p);
367 p.process_event(event6); pstate(p);
368 p.process_event(event1); pstate(p);
369 std::cout << "processing fork to SubFsm2::SubState2, SubFsm2::SubState2b and SubFsm2::SubState2c" << std::endl;
370 p.process_event(event3); pstate(p);
371 p.process_event(event1); pstate(p);
372 std::cout << "processing entry pseudo state" << std::endl;
373 p.process_event(event4); pstate(p);
374 p.process_event(event1); pstate(p);
375 std::cout << "processing entry + exit pseudo state" << std::endl;
376 p.process_event(event4); pstate(p);
377 std::cout << "using exit pseudo state" << std::endl;
378 p.process_event(event5); pstate(p);
379 }
380 }
381
main()382 int main()
383 {
384 test();
385 return 0;
386 }
387