]>
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 | // back-end | |
14 | #include <boost/msm/back/state_machine.hpp> | |
15 | //front-end | |
16 | #include <boost/msm/front/state_machine_def.hpp> | |
17 | ||
18 | namespace msm = boost::msm; | |
19 | namespace mpl = boost::mpl; | |
20 | ||
21 | namespace | |
22 | { | |
23 | // events | |
24 | struct event1 {}; | |
25 | struct event2 {}; | |
26 | struct event3 {}; | |
27 | struct event4 {}; | |
28 | struct event5 {}; | |
29 | struct event6 | |
30 | { | |
31 | event6(){} | |
32 | template <class Event> | |
33 | event6(Event const&){} | |
34 | }; | |
35 | // front-end: define the FSM structure | |
36 | struct Fsm_ : public msm::front::state_machine_def<Fsm_> | |
37 | { | |
38 | // The list of FSM states | |
39 | struct State1 : public msm::front::state<> | |
40 | { | |
41 | // every (optional) entry/exit methods get the event passed. | |
42 | template <class Event,class FSM> | |
43 | void on_entry(Event const&,FSM& ) {std::cout << "entering: State1" << std::endl;} | |
44 | template <class Event,class FSM> | |
45 | void on_exit(Event const&,FSM& ) {std::cout << "leaving: State1" << std::endl;} | |
46 | }; | |
47 | struct State2 : public msm::front::state<> | |
48 | { | |
49 | // every (optional) entry/exit methods get the event passed. | |
50 | template <class Event,class FSM> | |
51 | void on_entry(Event const&,FSM& ) {std::cout << "entering: State2" << std::endl;} | |
52 | template <class Event,class FSM> | |
53 | void on_exit(Event const&,FSM& ) {std::cout << "leaving: State2" << std::endl;} | |
54 | }; | |
55 | struct SubFsm2_ : public msm::front::state_machine_def<SubFsm2_> | |
56 | { | |
57 | typedef msm::back::state_machine<SubFsm2_> SubFsm2; | |
58 | ||
59 | template <class Event,class FSM> | |
60 | void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2" << std::endl;} | |
61 | template <class Event,class FSM> | |
62 | void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2" << std::endl;} | |
63 | ||
64 | struct SubState1 : public msm::front::state<> | |
65 | { | |
66 | template <class Event,class FSM> | |
67 | void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::SubState1" << std::endl;} | |
68 | template <class Event,class FSM> | |
69 | void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState1" << std::endl;} | |
70 | }; | |
71 | struct SubState1b : public msm::front::state<> | |
72 | { | |
73 | template <class Event,class FSM> | |
74 | void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::SubState1b" << std::endl;} | |
75 | template <class Event,class FSM> | |
76 | void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState1b" << std::endl;} | |
77 | }; | |
78 | struct SubState2 : public msm::front::state<> , public msm::front::explicit_entry<0> | |
79 | { | |
80 | template <class Event,class FSM> | |
81 | void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::SubState2" << std::endl;} | |
82 | template <class Event,class FSM> | |
83 | void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState2" << std::endl;} | |
84 | }; | |
85 | struct SubState2b : public msm::front::state<> , public msm::front::explicit_entry<1> | |
86 | { | |
87 | template <class Event,class FSM> | |
88 | void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::SubState2b" << std::endl;} | |
89 | template <class Event,class FSM> | |
90 | void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState2b" << std::endl;} | |
91 | }; | |
92 | // test with a pseudo entry | |
93 | struct PseudoEntry1 : public msm::front::entry_pseudo_state<0> | |
94 | { | |
95 | template <class Event,class FSM> | |
96 | void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::PseudoEntry1" << std::endl;} | |
97 | template <class Event,class FSM> | |
98 | void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::PseudoEntry1" << std::endl;} | |
99 | }; | |
100 | struct SubState3 : public msm::front::state<> | |
101 | { | |
102 | template <class Event,class FSM> | |
103 | void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::SubState3" << std::endl;} | |
104 | template <class Event,class FSM> | |
105 | void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState3" << std::endl;} | |
106 | }; | |
107 | struct SubState3b : public msm::front::state<> | |
108 | { | |
109 | template <class Event,class FSM> | |
110 | void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::SubState3b" << std::endl;} | |
111 | template <class Event,class FSM> | |
112 | void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState3b" << std::endl;} | |
113 | }; | |
114 | struct PseudoExit1 : public msm::front::exit_pseudo_state<event6> | |
115 | { | |
116 | template <class Event,class FSM> | |
117 | void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2::PseudoExit1" << std::endl;} | |
118 | template <class Event,class FSM> | |
119 | void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::PseudoExit1" << std::endl;} | |
120 | }; | |
121 | // action methods | |
122 | void entry_action(event4 const&) | |
123 | { | |
124 | std::cout << "calling entry_action" << std::endl; | |
125 | } | |
126 | // the initial state. Must be defined | |
127 | typedef mpl::vector<SubState1,SubState1b> initial_state; | |
128 | ||
129 | typedef mpl::vector<SubState2b> explicit_creation; | |
130 | ||
131 | // Transition table for SubFsm2 | |
132 | struct transition_table : mpl::vector< | |
133 | // Start Event Next Action Guard | |
134 | // +--------------+-------------+------------+------------------------+----------------------+ | |
135 | a_row < PseudoEntry1 , event4 , SubState3 ,&SubFsm2_::entry_action >, | |
136 | _row < SubState2 , event6 , SubState1 >, | |
137 | _row < SubState3 , event5 , PseudoExit1 > | |
138 | // +--------------+-------------+------------+------------------------+----------------------+ | |
139 | > {}; | |
140 | // Replaces the default no-transition response. | |
141 | template <class FSM,class Event> | |
142 | void no_transition(Event const& e, FSM&,int state) | |
143 | { | |
144 | std::cout << "no transition from state " << state | |
145 | << " on event " << typeid(e).name() << std::endl; | |
146 | } | |
147 | }; | |
148 | typedef msm::back::state_machine<SubFsm2_> SubFsm2; | |
149 | ||
150 | // the initial state of the player SM. Must be defined | |
151 | typedef State1 initial_state; | |
152 | ||
153 | // transition actions | |
154 | // guard conditions | |
155 | ||
156 | // Transition table for Fsm | |
157 | struct transition_table : mpl::vector< | |
158 | // Start Event Next Action Guard | |
159 | // +---------------------+--------+------------------------------------+-------+--------+ | |
160 | _row < State1 , event1 , SubFsm2 >, | |
161 | _row < State1 , event2 , SubFsm2::direct<SubFsm2_::SubState2> >, | |
162 | _row < State1 , event3 , mpl::vector<SubFsm2::direct<SubFsm2_::SubState2>, | |
163 | SubFsm2::direct<SubFsm2_::SubState2b> > >, | |
164 | _row < State1 , event4 , SubFsm2::entry_pt | |
165 | <SubFsm2_::PseudoEntry1> >, | |
166 | // +---------------------+--------+------------------------------------+-------+--------+ | |
167 | _row < SubFsm2 , event1 , State1 >, | |
168 | _row < SubFsm2::exit_pt | |
169 | <SubFsm2_::PseudoExit1>, event6 , State2 > | |
170 | // +---------------------+--------+------------------------------------+-------+--------+ | |
171 | > {}; | |
172 | ||
173 | // Replaces the default no-transition response. | |
174 | template <class FSM,class Event> | |
175 | void no_transition(Event const& e, FSM&,int state) | |
176 | { | |
177 | std::cout << "no transition from state " << state | |
178 | << " on event " << typeid(e).name() << std::endl; | |
179 | } | |
180 | }; | |
181 | typedef msm::back::state_machine<Fsm_> Fsm; | |
182 | ||
183 | // | |
184 | // Testing utilities. | |
185 | // | |
186 | static char const* const state_names[] = { "State1", "SubFsm2","State2" }; | |
187 | void pstate(Fsm const& p) | |
188 | { | |
189 | std::cout << " -> " << state_names[p.current_state()[0]] << std::endl; | |
190 | } | |
191 | ||
192 | void test() | |
193 | { | |
194 | Fsm p; | |
195 | // needed to start the highest-level SM. This will call on_entry and mark the start of the SM | |
196 | p.start(); | |
197 | std::cout << "Simply move in and out of the composite, activate init states" << std::endl; | |
198 | p.process_event(event1()); pstate(p); | |
199 | p.process_event(event1()); pstate(p); | |
200 | std::cout << "Direct entry into SubFsm2::SubState2, then transition to SubState1 and back to State1" << std::endl; | |
201 | p.process_event(event2()); pstate(p); | |
202 | p.process_event(event6()); pstate(p); | |
203 | p.process_event(event1()); pstate(p); | |
204 | std::cout << "processing fork to SubFsm2::SubState2 and SubFsm2::SubState2b" << std::endl; | |
205 | p.process_event(event3()); pstate(p); | |
206 | p.process_event(event1()); pstate(p); | |
207 | std::cout << "processing entry pseudo state" << std::endl; | |
208 | p.process_event(event4()); pstate(p); | |
209 | p.process_event(event1()); pstate(p); | |
210 | std::cout << "processing entry + exit pseudo state" << std::endl; | |
211 | p.process_event(event4()); pstate(p); | |
212 | std::cout << "using exit pseudo state" << std::endl; | |
213 | p.process_event(event5()); pstate(p); | |
214 | } | |
215 | } | |
216 | ||
217 | int main() | |
218 | { | |
219 | test(); | |
220 | return 0; | |
221 | } |