]>
Commit | Line | Data |
---|---|---|
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 | { | |
34 | event6_impl(){} | |
35 | template <class Event> | |
36 | event6_impl(Event const&){} | |
37 | }; | |
38 | event6_impl const event6; | |
39 | ||
40 | //Sub fsm state definition | |
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 | }; | |
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 | ||
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 | }; | |
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 | ||
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 | }; | |
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 | ||
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 | }; | |
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 | ||
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 | }; | |
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 | ||
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 | }; | |
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 | ||
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 | }; | |
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 | ||
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 | }; | |
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 | ||
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 | }; | |
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 | ||
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 | }; | |
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 | |
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 | |
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 | }; | |
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 | |
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 | }; | |
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 | ||
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 | }; | |
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 | ||
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" }; | |
352 | void pstate(Fsm const& p) | |
353 | { | |
354 | std::cout << " -> " << state_names[p.current_state()[0]] << std::endl; | |
355 | } | |
356 | ||
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 | ||
382 | int main() | |
383 | { | |
384 | test(); | |
385 | return 0; | |
386 | } |