1 | // Copyright 2024 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 <boost/msm/front/puml/puml.hpp> |
12 | |
13 | using namespace boost::msm::front; |
14 | using namespace boost::msm::front::puml; |
15 | namespace boost::msm::front::puml { |
16 | // events |
17 | template<> |
18 | struct Event<by_name(str: "play" )> { int cpt_ = 0; }; |
19 | template<> |
20 | struct Event<by_name(str: "end_pause" )> { int cpt_ = 0; }; |
21 | template<> |
22 | struct Event<by_name(str: "stop" )> {}; |
23 | template<> |
24 | struct Event<by_name(str: "pause" )> {}; |
25 | template<> |
26 | struct Event<by_name(str: "open_close" )> {}; |
27 | template<> |
28 | struct Event<by_name(str: "internal_evt" )> {}; |
29 | template<> |
30 | struct Event<by_name(str: "to_ignore" )> {}; |
31 | // A "complicated" event type that carries some data. |
32 | enum DiskTypeEnum |
33 | { |
34 | DISK_CD = 0, |
35 | DISK_DVD = 1 |
36 | }; |
37 | template<> |
38 | struct Event<by_name(str: "cd_detected" )> |
39 | { |
40 | Event(std::string name, DiskTypeEnum diskType= DISK_CD) |
41 | : name(name), |
42 | disc_type(diskType) |
43 | {} |
44 | |
45 | std::string name; |
46 | DiskTypeEnum disc_type; |
47 | }; |
48 | |
49 | // The list of FSM states |
50 | template<> |
51 | struct State<by_name(str: "Empty" )> : public msm::front::state<> |
52 | { |
53 | template <class Event, class FSM> |
54 | void on_entry(Event const&, FSM&) { ++entry_counter; } |
55 | template <class Event, class FSM> |
56 | void on_exit(Event const&, FSM&) { ++exit_counter; } |
57 | int entry_counter = 0; |
58 | int exit_counter = 0; |
59 | unsigned int empty_internal_guard_counter = 0; |
60 | unsigned int empty_internal_action_counter = 0; |
61 | }; |
62 | template<> |
63 | struct State<by_name(str: "Open" )> : public msm::front::state<> |
64 | { |
65 | template <class Event, class FSM> |
66 | void on_entry(Event const&, FSM&) { ++entry_counter; } |
67 | template <class Event, class FSM> |
68 | void on_exit(Event const&, FSM&) { ++exit_counter; } |
69 | int entry_counter = 0; |
70 | int exit_counter = 0; |
71 | }; |
72 | template<> |
73 | struct State<by_name(str: "Stopped" )> : public msm::front::state<> |
74 | { |
75 | template <class Event, class FSM> |
76 | void on_entry(Event const&, FSM&) { ++entry_counter; } |
77 | template <class Event, class FSM> |
78 | void on_exit(Event const&, FSM&) { ++exit_counter; } |
79 | int entry_counter = 0; |
80 | int exit_counter = 0; |
81 | }; |
82 | template<> |
83 | struct State<by_name(str: "Paused" )> : public msm::front::state<> |
84 | { |
85 | template <class Event, class FSM> |
86 | void on_entry(Event const&, FSM&) { ++entry_counter; } |
87 | template <class Event, class FSM> |
88 | void on_exit(Event const&, FSM&) { ++exit_counter; } |
89 | int entry_counter = 0; |
90 | int exit_counter = 0; |
91 | }; |
92 | template<> |
93 | struct State<by_name(str: "Playing" )> : public msm::front::state<> |
94 | { |
95 | template <class Event, class FSM> |
96 | void on_entry(Event const&, FSM&) { ++entry_counter; } |
97 | template <class Event, class FSM> |
98 | void on_exit(Event const&, FSM&) { ++exit_counter; } |
99 | int entry_counter = 0; |
100 | int exit_counter = 0; |
101 | }; |
102 | template<> |
103 | struct State<by_name(str: "Playing2" )> : public msm::front::state<> |
104 | { |
105 | template <class Event, class FSM> |
106 | void on_entry(Event const& e, FSM&) |
107 | { |
108 | ++entry_counter; |
109 | event_counter = e.cpt_; |
110 | } |
111 | template <class Event, class FSM> |
112 | void on_exit(Event const&, FSM&) { ++exit_counter; } |
113 | int entry_counter = 0; |
114 | int exit_counter = 0; |
115 | int event_counter = 0; |
116 | }; |
117 | //actions |
118 | template<> |
119 | struct Action<by_name(str: "open_drawer" )> |
120 | { |
121 | template <class EVT, class FSM, class SourceState, class TargetState> |
122 | void operator()(EVT const&, FSM&, SourceState&, TargetState&) |
123 | { |
124 | } |
125 | }; |
126 | template<> |
127 | struct Action<by_name(str: "close_drawer" )> |
128 | { |
129 | template <class EVT, class FSM, class SourceState, class TargetState> |
130 | void operator()(EVT const&, FSM&, SourceState&, TargetState&) |
131 | { |
132 | } |
133 | }; |
134 | template<> |
135 | struct Action<by_name(str: "start_playback" )> |
136 | { |
137 | template <class EVT, class FSM, class SourceState, class TargetState> |
138 | void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&) |
139 | { |
140 | ++fsm.start_playback_counter; |
141 | } |
142 | }; |
143 | template<> |
144 | struct Action<by_name(str: "store_cd_info" )> |
145 | { |
146 | template <class EVT, class FSM, class SourceState, class TargetState> |
147 | void operator()(EVT const&, FSM&, SourceState&, TargetState&) |
148 | { |
149 | } |
150 | }; |
151 | template<> |
152 | struct Action<by_name(str: "store_cd_info2" )> |
153 | { |
154 | template <class EVT, class FSM, class SourceState, class TargetState> |
155 | void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&) |
156 | { |
157 | fsm.process_event(Event<by_name(str: "play" )>{}); |
158 | } |
159 | }; |
160 | template<> |
161 | struct Action<by_name(str: "stop_playback" )> |
162 | { |
163 | template <class EVT, class FSM, class SourceState, class TargetState> |
164 | void operator()(EVT const&, FSM&, SourceState&, TargetState&) |
165 | { |
166 | } |
167 | }; |
168 | template<> |
169 | struct Action<by_name(str: "pause_playback" )> |
170 | { |
171 | template <class EVT, class FSM, class SourceState, class TargetState> |
172 | void operator()(EVT const&, FSM&, SourceState&, TargetState&) |
173 | { |
174 | } |
175 | }; |
176 | template<> |
177 | struct Action<by_name(str: "resume_playback" )> |
178 | { |
179 | template <class EVT, class FSM, class SourceState, class TargetState> |
180 | void operator()(EVT&, FSM&, SourceState&, TargetState&) |
181 | { |
182 | } |
183 | }; |
184 | template<> |
185 | struct Action<by_name(str: "resume_playback2" )> |
186 | { |
187 | template <class EVT, class FSM, class SourceState, class TargetState> |
188 | void operator()(EVT& e, FSM&, SourceState&, TargetState&) |
189 | { |
190 | ++e.cpt_; |
191 | } |
192 | }; |
193 | template<> |
194 | struct Action<by_name(str: "stop_and_open" )> |
195 | { |
196 | template <class EVT, class FSM, class SourceState, class TargetState> |
197 | void operator()(EVT const&, FSM&, SourceState&, TargetState&) |
198 | { |
199 | } |
200 | }; |
201 | template<> |
202 | struct Action<by_name(str: "stopped_again" )> |
203 | { |
204 | template <class EVT, class FSM, class SourceState, class TargetState> |
205 | void operator()(EVT const&, FSM&, SourceState&, TargetState&) |
206 | { |
207 | } |
208 | }; |
209 | template<> |
210 | struct Action<by_name(str: "internal_action" )> |
211 | { |
212 | template <class EVT, class FSM, class SourceState, class TargetState> |
213 | void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&) |
214 | { |
215 | ++fsm.internal_action_counter; |
216 | } |
217 | }; |
218 | template<> |
219 | struct Action<by_name(str: "internal_action_fct" )> |
220 | { |
221 | template <class EVT, class FSM, class SourceState, class TargetState> |
222 | void operator()(EVT const&, FSM&, SourceState& src, TargetState&) |
223 | { |
224 | ++src.empty_internal_action_counter; |
225 | } |
226 | }; |
227 | |
228 | template<> |
229 | struct Action<by_name(str: "TestFct" )> |
230 | { |
231 | template <class EVT, class FSM, class SourceState, class TargetState> |
232 | void operator()(EVT& e, FSM& fsm, SourceState&, TargetState&) |
233 | { |
234 | ++e.cpt_; |
235 | ++fsm.test_fct_counter; |
236 | } |
237 | }; |
238 | template<> |
239 | struct Action<by_name(str: "increment_entry" )> |
240 | { |
241 | template <class EVT, class FSM, class SourceState, class TargetState> |
242 | void operator()(EVT&, FSM& fsm, SourceState&, TargetState&) |
243 | { |
244 | ++fsm.entry_counter; |
245 | } |
246 | }; |
247 | template<> |
248 | struct Action<by_name(str: "increment_exit" )> |
249 | { |
250 | template <class EVT, class FSM, class SourceState, class TargetState> |
251 | void operator()(EVT&, FSM& fsm, SourceState&, TargetState&) |
252 | { |
253 | ++fsm.exit_counter; |
254 | } |
255 | }; |
256 | |
257 | // guard conditions |
258 | template<> |
259 | struct Guard<by_name(str: "good_disk_format" )> |
260 | { |
261 | template <class EVT, class FSM, class SourceState, class TargetState> |
262 | bool operator()(EVT& evt, FSM&, SourceState&, TargetState&) |
263 | { |
264 | // to test a guard condition, let's say we understand only CDs, not DVD |
265 | if (evt.disc_type != DISK_CD) |
266 | { |
267 | return false; |
268 | } |
269 | return true; |
270 | } |
271 | }; |
272 | template<> |
273 | struct Guard<by_name(str: "can_close_drawer" )> |
274 | { |
275 | template <class EVT, class FSM, class SourceState, class TargetState> |
276 | bool operator()(EVT const&, FSM& fsm, SourceState&, TargetState&) |
277 | { |
278 | ++fsm.can_close_drawer_counter; |
279 | return true; |
280 | } |
281 | }; |
282 | template<> |
283 | struct Guard<by_name(str: "internal_guard" )> |
284 | { |
285 | template <class EVT, class FSM, class SourceState, class TargetState> |
286 | bool operator()(EVT const&, FSM& fsm, SourceState&, TargetState&) |
287 | { |
288 | ++fsm.internal_guard_counter; |
289 | return false; |
290 | } |
291 | }; |
292 | template<> |
293 | struct Guard<by_name(str: "internal_guard_fct" )> |
294 | { |
295 | template <class EVT, class FSM, class SourceState, class TargetState> |
296 | bool operator()(EVT const&, FSM&, SourceState& src, TargetState&) |
297 | { |
298 | ++src.empty_internal_guard_counter; |
299 | return false; |
300 | } |
301 | }; |
302 | template<> |
303 | struct Guard<by_name(str: "internal_guard2" )> |
304 | { |
305 | template <class EVT, class FSM, class SourceState, class TargetState> |
306 | bool operator()(EVT const&, FSM& fsm, SourceState&, TargetState&) |
307 | { |
308 | ++fsm.internal_guard_counter; |
309 | return true; |
310 | } |
311 | }; |
312 | template<> |
313 | struct Guard<by_name(str: "DummyGuard" )> |
314 | { |
315 | template <class EVT, class FSM, class SourceState, class TargetState> |
316 | bool operator()(EVT const&, FSM&, SourceState&, TargetState&) |
317 | { |
318 | return true; |
319 | } |
320 | }; |
321 | template<> |
322 | struct Guard<by_name(str: "always_true" )> |
323 | { |
324 | template <class EVT, class FSM, class SourceState, class TargetState> |
325 | bool operator()(EVT const&, FSM&, SourceState&, TargetState&) |
326 | { |
327 | return true; |
328 | } |
329 | }; |
330 | } |
331 | |
332 | |