Embedded Template Library 1.0
fsm_generator.h
1/******************************************************************************
2The MIT License(MIT)
3
4Embedded Template Library.
5https://github.com/ETLCPP/etl
6https://www.etlcpp.com
7
8Copyright(c) 2017 John Wellbelove
9
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files(the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions :
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27******************************************************************************/
28
29/*[[[cog
30import cog
31cog.outl("#if 0")
32]]]*/
33/*[[[end]]]*/
34#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
35/*[[[cog
36import cog
37cog.outl("#endif")
38]]]*/
39/*[[[end]]]*/
40
41/*[[[cog
42import cog
43cog.outl("//***************************************************************************")
44cog.outl("// THIS FILE HAS BEEN AUTO GENERATED. DO NOT EDIT THIS FILE.")
45cog.outl("//***************************************************************************")
46]]]*/
47/*[[[end]]]*/
48
49//***************************************************************************
50// To generate to header file, run this at the command line.
51// Note: You will need Python and COG installed.
52//
53// python -m cogapp -d -e -ofsm.h -DHandlers=<n> fsm_generator.h
54// Where <n> is the number of messages to support.
55//
56// e.g.
57// To generate handlers for up to 16 events...
58// python -m cogapp -d -e -ofsm.h -DHandlers=16 fsm_generator.h
59//
60// See generate.bat
61//***************************************************************************
62
63#ifndef ETL_FSM_INCLUDED
64#define ETL_FSM_INCLUDED
65
66#include "platform.h"
67#include "array.h"
68#include "nullptr.h"
69#include "error_handler.h"
70#include "exception.h"
71#include "user_type.h"
72#include "message_router.h"
73#include "integral_limits.h"
74#include "largest.h"
75
76#include <stdint.h>
77
78#include "private/minmax_push.h"
79
80namespace etl
81{
82 class fsm;
83 class hfsm;
84
86#if !defined(ETL_FSM_STATE_ID_TYPE)
87 typedef uint_least8_t fsm_state_id_t;
88#else
89 typedef ETL_FSM_STATE_ID_TYPE fsm_state_id_t;
90#endif
91
92 // For internal FSM use.
93 typedef typename etl::larger_type<etl::message_id_t>::type fsm_internal_id_t;
94
95#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
96 template <typename, typename, etl::fsm_state_id_t, typename...>
97 class fsm_state;
98#else
99 /*[[[cog
100 import cog
101 cog.outl("template <typename, typename, etl::fsm_state_id_t,")
102 cog.out(" ")
103 for n in range(1, int(Handlers)):
104 cog.out("typename, ")
105 if n % 4 == 0:
106 cog.outl("")
107 cog.out(" ")
108 cog.outl("typename>")
109 cog.outl("class fsm_state;")
110 ]]]*/
111 /*[[[end]]]*/
112#endif
113
114 //***************************************************************************
116 //***************************************************************************
117 class fsm_exception : public etl::exception
118 {
119 public:
120
121 fsm_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
122 : etl::exception(reason_, file_name_, line_number_)
123 {
124 }
125 };
126
127 //***************************************************************************
129 //***************************************************************************
130 class fsm_null_state_exception : public etl::fsm_exception
131 {
132 public:
133
134 fsm_null_state_exception(string_type file_name_, numeric_type line_number_)
135 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:null state", ETL_FSM_FILE_ID"A"), file_name_, line_number_)
136 {
137 }
138 };
139
140 //***************************************************************************
142 //***************************************************************************
143 class fsm_state_id_exception : public etl::fsm_exception
144 {
145 public:
146
147 fsm_state_id_exception(string_type file_name_, numeric_type line_number_)
148 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:state id", ETL_FSM_FILE_ID"B"), file_name_, line_number_)
149 {
150 }
151 };
152
153 //***************************************************************************
155 //***************************************************************************
156 class fsm_state_list_exception : public etl::fsm_exception
157 {
158 public:
159
160 fsm_state_list_exception(string_type file_name_, numeric_type line_number_)
161 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:state list", ETL_FSM_FILE_ID"C"), file_name_, line_number_)
162 {
163 }
164 };
165
166 //***************************************************************************
168 //***************************************************************************
169 class fsm_state_list_order_exception : public etl::fsm_exception
170 {
171 public:
172
173 fsm_state_list_order_exception(string_type file_name_, numeric_type line_number_)
174 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:state list order", ETL_FSM_FILE_ID"D"), file_name_, line_number_)
175 {
176 }
177 };
178
179 //***************************************************************************
181 //***************************************************************************
182 class fsm_state_composite_state_change_forbidden : public etl::fsm_exception
183 {
184 public:
185 fsm_state_composite_state_change_forbidden(string_type file_name_, numeric_type line_number_)
186 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:change in composite state forbidden", ETL_FSM_FILE_ID"E"), file_name_, line_number_)
187 {
188 }
189 };
190
191 namespace private_fsm
192 {
193 template <typename T = void>
194 class ifsm_state_helper
195 {
196 public:
197
198 // Pass this whenever no state change is desired.
199 // The highest unsigned value of fsm_state_id_t.
200 static ETL_CONSTANT fsm_state_id_t No_State_Change = etl::integral_limits<fsm_state_id_t>::max;
201
202 // Pass this when this event also needs to be passed to the parent.
203 static ETL_CONSTANT fsm_state_id_t Pass_To_Parent = No_State_Change - 1U;
204 };
205
206 template <typename T>
207 ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::No_State_Change;
208
209 template <typename T>
210 ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::Pass_To_Parent;
211 }
212
213 //***************************************************************************
215 //***************************************************************************
216 class ifsm_state : public private_fsm::ifsm_state_helper<>
217 {
218 public:
219
221 friend class etl::fsm;
222 friend class etl::hfsm;
223
224 using private_fsm::ifsm_state_helper<>::No_State_Change;
225 using private_fsm::ifsm_state_helper<>::Pass_To_Parent;
226
227#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
228 template <typename, typename, etl::fsm_state_id_t, typename...>
229 friend class fsm_state;
230#else
231 /*[[[cog
232 import cog
233 cog.outl(" template <typename, typename, etl::fsm_state_id_t,")
234 cog.out(" ")
235 for n in range(1, int(Handlers)):
236 cog.out("typename, ")
237 if n % 4 == 0:
238 cog.outl("")
239 cog.out(" ")
240 cog.outl("typename>")
241 ]]]*/
242 /*[[[end]]]*/
243 friend class etl::fsm_state;
244#endif
245
246 //*******************************************
248 //*******************************************
250 {
251 return state_id;
252 }
253
254 //*******************************************
257 //*******************************************
259 {
260 ETL_ASSERT(state.p_parent == ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
261 state.p_parent = this;
262
263 if (p_default_child == ETL_NULLPTR)
264 {
265 p_active_child = &state;
266 p_default_child = &state;
267 }
268 }
269
270 //*******************************************
273 //*******************************************
274 template <typename TSize>
275 void set_child_states(etl::ifsm_state** state_list, TSize size)
276 {
277 p_active_child = ETL_NULLPTR;
278 p_default_child = ETL_NULLPTR;
279
280 for (TSize i = 0; i < size; ++i)
281 {
282 ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
283 add_child_state(*state_list[i]);
284 }
285 }
286
287 protected:
288
289 //*******************************************
291 //*******************************************
293 : state_id(state_id_),
294 p_context(ETL_NULLPTR),
295 p_parent(ETL_NULLPTR),
296 p_active_child(ETL_NULLPTR),
297 p_default_child(ETL_NULLPTR)
298 {
299 }
300
301 //*******************************************
303 //*******************************************
304 virtual ~ifsm_state()
305 {
306 }
307
308 //*******************************************
309 etl::fsm& get_fsm_context() const
310 {
311 return *p_context;
312 }
313
314 private:
315
316 virtual fsm_state_id_t process_event(const etl::imessage& message) = 0;
317
318 virtual fsm_state_id_t on_enter_state() { return No_State_Change; } // By default, do nothing.
319 virtual void on_exit_state() {} // By default, do nothing.
320
321 //*******************************************
322 void set_fsm_context(etl::fsm& context)
323 {
324 p_context = &context;
325 }
326
327 // The state id.
328 const etl::fsm_state_id_t state_id;
329
330 // A pointer to the FSM context.
331 etl::fsm* p_context;
332
333 // A pointer to the parent.
334 ifsm_state* p_parent;
335
336 // A pointer to the active child.
337 ifsm_state* p_active_child;
338
339 // A pointer to the default active child.
340 ifsm_state* p_default_child;
341
342 // Disabled.
343 ifsm_state(const ifsm_state&);
344 ifsm_state& operator =(const ifsm_state&);
345 };
346
347 //***************************************************************************
349 //***************************************************************************
350 class fsm : public etl::imessage_router
351 {
352 public:
353
354 friend class etl::hfsm;
355 using imessage_router::receive;
356
357 //*******************************************
359 //*******************************************
360 fsm(etl::message_router_id_t id)
361 : imessage_router(id)
362 , p_state(ETL_NULLPTR)
363 , state_list(ETL_NULLPTR)
364 , number_of_states(0U)
365 {
366 }
367
368 //*******************************************
370 //*******************************************
371 template <typename TSize>
372 void set_states(etl::ifsm_state** p_states, TSize size)
373 {
374 state_list = p_states;
375 number_of_states = etl::fsm_state_id_t(size);
376
377 ETL_ASSERT(number_of_states > 0, ETL_ERROR(etl::fsm_state_list_exception));
378 ETL_ASSERT(number_of_states < ifsm_state::No_State_Change, ETL_ERROR(etl::fsm_state_list_exception));
379
380 for (etl::fsm_state_id_t i = 0; i < size; ++i)
381 {
382 ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
383 ETL_ASSERT(state_list[i]->get_state_id() == i, ETL_ERROR(etl::fsm_state_list_order_exception));
384 state_list[i]->set_fsm_context(*this);
385 }
386 }
387
388 //*******************************************
393 //*******************************************
394 virtual void start(bool call_on_enter_state = true)
395 {
396 // Can only be started once.
397 if (p_state == ETL_NULLPTR)
398 {
399 p_state = state_list[0];
400 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
401
402 if (call_on_enter_state)
403 {
404 etl::fsm_state_id_t next_state_id;
405 etl::ifsm_state* p_last_state;
406
407 do
408 {
409 p_last_state = p_state;
410 next_state_id = p_state->on_enter_state();
411 if (next_state_id != ifsm_state::No_State_Change)
412 {
413 ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
414 p_state = state_list[next_state_id];
415 }
416 } while (p_last_state != p_state);
417 }
418 }
419 }
420
421 //*******************************************
423 //*******************************************
424 void receive(const etl::imessage& message) ETL_OVERRIDE
425 {
426 etl::fsm_state_id_t next_state_id = p_state->process_event(message);
427
428 if (have_changed_state(next_state_id))
429 {
430 ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
431 etl::ifsm_state* p_next_state = state_list[next_state_id];
432
433 do
434 {
435 p_state->on_exit_state();
436 p_state = p_next_state;
437
438 next_state_id = p_state->on_enter_state();
439
440 if (have_changed_state(next_state_id))
441 {
442 ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
443 p_next_state = state_list[next_state_id];
444 }
445 } while (p_next_state != p_state); // Have we changed state again?
446 }
447 }
448
449 using imessage_router::accepts;
450
451 //*******************************************
454 //*******************************************
455 bool accepts(etl::message_id_t) const ETL_OVERRIDE
456 {
457 return true;
458 }
459
460 //*******************************************
462 //*******************************************
464 {
465 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
466 return p_state->get_state_id();
467 }
468
469 //*******************************************
471 //*******************************************
473 {
474 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
475 return *p_state;
476 }
477
478 //*******************************************
480 //*******************************************
481 const ifsm_state& get_state() const
482 {
483 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
484 return *p_state;
485 }
486
487 //*******************************************
489 //*******************************************
490 bool is_started() const
491 {
492 return p_state != ETL_NULLPTR;
493 }
494
495 //*******************************************
498 //*******************************************
499 virtual void reset(bool call_on_exit_state = false)
500 {
501 if ((p_state != ETL_NULLPTR) && call_on_exit_state)
502 {
503 p_state->on_exit_state();
504 }
505
506 p_state = ETL_NULLPTR;
507 }
508
509 //********************************************
510 ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
511 {
512 return false;
513 }
514
515 //********************************************
516 bool is_producer() const ETL_OVERRIDE
517 {
518 return true;
519 }
520
521 //********************************************
522 bool is_consumer() const ETL_OVERRIDE
523 {
524 return true;
525 }
526
527 private:
528
529 //********************************************
530 bool have_changed_state(etl::fsm_state_id_t next_state_id) const
531 {
532 return (next_state_id != p_state->get_state_id()) &&
533 (next_state_id != ifsm_state::No_State_Change);
534 }
535
536 etl::ifsm_state* p_state;
537 etl::ifsm_state** state_list;
538 etl::fsm_state_id_t number_of_states;
539 };
540
541 //*************************************************************************************************
542 // For C++17 and above.
543 //*************************************************************************************************
544#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
545 //***************************************************************************
546 // The definition for all types.
547 //***************************************************************************
548 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
549 class fsm_state : public ifsm_state
550 {
551 public:
552
553 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
554
555 fsm_state()
556 : ifsm_state(STATE_ID)
557 {
558 }
559
560 protected:
561
562 ~fsm_state()
563 {
564 }
565
566 TContext& get_fsm_context() const
567 {
568 return static_cast<TContext&>(ifsm_state::get_fsm_context());
569 }
570
571 private:
572
573 //********************************************
574 struct result_t
575 {
576 bool was_handled;
577 etl::fsm_state_id_t state_id;
578 };
579
580 //********************************************
581 etl::fsm_state_id_t process_event(const etl::imessage& message)
582 {
583 etl::fsm_state_id_t new_state_id;
584
585 const bool was_handled = (process_event_type<TMessageTypes>(message, new_state_id) || ...);
586
587 if (!was_handled || (new_state_id == Pass_To_Parent))
588 {
589 new_state_id = (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
590 }
591
592 return new_state_id;
593 }
594
595 //********************************************
596 template <typename TMessage>
597 bool process_event_type(const etl::imessage& msg, etl::fsm_state_id_t& state_id)
598 {
599 if (TMessage::ID == msg.get_message_id())
600 {
601 state_id = static_cast<TDerived*>(this)->on_event(static_cast<const TMessage&>(msg));
602 return true;
603 }
604 else
605 {
606 return false;
607 }
608 }
609 };
610
612 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
613 ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::STATE_ID;
614
615#else
616//*************************************************************************************************
617// For C++14 and below.
618//*************************************************************************************************
619 /*[[[cog
620 import cog
621 ################################################
622 # The first definition for all of the events.
623 ################################################
624 cog.outl("//***************************************************************************")
625 cog.outl("// The definition for all %s message types." % Handlers)
626 cog.outl("//***************************************************************************")
627 cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, ")
628 cog.out(" ")
629 for n in range(1, int(Handlers)):
630 cog.out("typename T%s = void, " % n)
631 if n % 4 == 0:
632 cog.outl("")
633 cog.out(" ")
634 cog.outl("typename T%s = void>" % Handlers)
635 cog.outl("class fsm_state : public ifsm_state")
636 cog.outl("{")
637 cog.outl("public:")
638 cog.outl("")
639 cog.outl(" static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;")
640 cog.outl("")
641 cog.outl(" fsm_state()")
642 cog.outl(" : ifsm_state(STATE_ID)")
643 cog.outl(" {")
644 cog.outl(" }")
645 cog.outl("")
646 cog.outl("protected:")
647 cog.outl("")
648 cog.outl(" ~fsm_state()")
649 cog.outl(" {")
650 cog.outl(" }")
651 cog.outl("")
652 cog.outl(" TContext& get_fsm_context() const")
653 cog.outl(" {")
654 cog.outl(" return static_cast<TContext&>(ifsm_state::get_fsm_context());")
655 cog.outl(" }")
656 cog.outl("")
657 cog.outl("private:")
658 cog.outl("")
659 cog.outl(" etl::fsm_state_id_t process_event(const etl::imessage& message)")
660 cog.outl(" {")
661 cog.outl(" etl::fsm_state_id_t new_state_id;")
662 cog.outl(" etl::message_id_t event_id = message.get_message_id();")
663 cog.outl("")
664 cog.outl(" switch (event_id)")
665 cog.outl(" {")
666 for n in range(1, int(Handlers) + 1):
667 cog.out(" case T%d::ID:" % n)
668 cog.out(" new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T%d&>(message));" % n)
669 cog.outl(" break;")
670 cog.out(" default:")
671 cog.out(" new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);")
672 cog.outl(" break;")
673 cog.outl(" }")
674 cog.outl("")
675 cog.outl(" return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);")
676 cog.outl(" }")
677 cog.outl("};")
678
679 ####################################
680 # All of the other specialisations.
681 ####################################
682 for n in range(int(Handlers) - 1, 0, -1):
683 cog.outl("")
684 cog.outl("//***************************************************************************")
685 if n == 1:
686 cog.outl("// Specialisation for %d message type." % n)
687 else:
688 cog.outl("// Specialisation for %d message types." % n)
689 cog.outl("//***************************************************************************")
690 cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, ")
691 cog.out(" ")
692 for t in range(1, n):
693 cog.out("typename T%d, " % t)
694 if t % 4 == 0:
695 cog.outl("")
696 cog.out(" ")
697 cog.outl("typename T%d>" % n)
698 cog.out("class fsm_state<TContext, TDerived, STATE_ID_, ")
699 for t in range(1, n + 1):
700 cog.out("T%d, " % t)
701 if t % 16 == 0:
702 cog.outl("")
703 cog.out(" ")
704 for t in range(n + 1, int(Handlers)):
705 cog.out("void, ")
706 if t % 16 == 0:
707 cog.outl("")
708 cog.out(" ")
709 cog.outl("void> : public ifsm_state")
710 cog.outl("{")
711 cog.outl("public:")
712 cog.outl("")
713 cog.outl(" static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;")
714 cog.outl("")
715 cog.outl(" fsm_state()")
716 cog.outl(" : ifsm_state(STATE_ID)")
717 cog.outl(" {")
718 cog.outl(" }")
719 cog.outl("")
720 cog.outl("protected:")
721 cog.outl("")
722 cog.outl(" ~fsm_state()")
723 cog.outl(" {")
724 cog.outl(" }")
725 cog.outl("")
726 cog.outl(" TContext& get_fsm_context() const")
727 cog.outl(" {")
728 cog.outl(" return static_cast<TContext&>(ifsm_state::get_fsm_context());")
729 cog.outl(" }")
730 cog.outl("")
731 cog.outl("private:")
732 cog.outl("")
733 cog.outl(" etl::fsm_state_id_t process_event(const etl::imessage& message)")
734 cog.outl(" {")
735 cog.outl(" etl::fsm_state_id_t new_state_id;")
736 cog.outl(" etl::message_id_t event_id = message.get_message_id();")
737 cog.outl("")
738 cog.outl(" switch (event_id)")
739 cog.outl(" {")
740 for n in range(1, n + 1):
741 cog.out(" case T%d::ID:" % n)
742 cog.out(" new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T%d&>(message));" % n)
743 cog.outl(" break;")
744 cog.out(" default:")
745 cog.out(" new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);")
746 cog.outl(" break;")
747 cog.outl(" }")
748 cog.outl("")
749 cog.outl(" return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);")
750 cog.outl(" }")
751 cog.outl("};")
752 ####################################
753 # Specialisation for zero messages.
754 ####################################
755 cog.outl("")
756 cog.outl("//***************************************************************************")
757 cog.outl("// Specialisation for 0 message types.")
758 cog.outl("//***************************************************************************")
759 cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_>")
760 cog.out("class fsm_state<TContext, TDerived, STATE_ID_, ")
761 for t in range(1, int(Handlers)):
762 cog.out("void, ")
763 if t % 16 == 0:
764 cog.outl("")
765 cog.out(" ")
766 cog.outl("void> : public ifsm_state")
767 cog.outl("{")
768 cog.outl("public:")
769 cog.outl("")
770 cog.outl(" static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;")
771 cog.outl("")
772 cog.outl(" fsm_state()")
773 cog.outl(" : ifsm_state(STATE_ID)")
774 cog.outl(" {")
775 cog.outl(" }")
776 cog.outl("")
777 cog.outl("protected:")
778 cog.outl("")
779 cog.outl(" ~fsm_state()")
780 cog.outl(" {")
781 cog.outl(" }")
782 cog.outl("")
783 cog.outl(" TContext& get_fsm_context() const")
784 cog.outl(" {")
785 cog.outl(" return static_cast<TContext&>(ifsm_state::get_fsm_context());")
786 cog.outl(" }")
787 cog.outl("private:")
788 cog.outl("")
789 cog.outl(" etl::fsm_state_id_t process_event(const etl::imessage& message)")
790 cog.outl(" {")
791 cog.outl(" return p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);")
792 cog.outl(" }")
793 cog.outl("};")
794
795 cog.outl("")
796 cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, ")
797 cog.out(" ")
798 for n in range(1, int(Handlers)):
799 cog.out("typename T%s, " % n)
800 if n % 4 == 0:
801 cog.outl("")
802 cog.out(" ")
803 cog.outl("typename T%s>" % Handlers)
804 cog.out("ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, ")
805 for n in range(1, int(Handlers)):
806 cog.out("T%s, " % n)
807 cog.outl("T%s>::STATE_ID;" % Handlers)
808 ]]]*/
809 /*[[[end]]]*/
810#endif
811}
812
813#include "private/minmax_pop.h"
814
815#endif
Base exception class for FSM.
Definition: fsm.h:99
Exception for null state pointer.
Definition: fsm.h:112
Exception for invalid state id.
Definition: fsm.h:125
Exception for incompatible state list.
Definition: fsm.h:138
Exception for incompatible order state list.
Definition: fsm.h:151
Definition: fsm.h:602
The FSM class.
Definition: fsm.h:325
etl::fsm_state_id_t get_state_id() const
Gets the current state id.
Definition: fsm_generator.h:463
void receive(const etl::imessage &message) ETL_OVERRIDE
Top level message handler for the FSM.
Definition: fsm_generator.h:424
virtual void start(bool call_on_enter_state=true)
Starts the FSM. Can only be called once. Subsequent calls will do nothing.
Definition: fsm_generator.h:394
fsm(etl::message_router_id_t id)
Constructor.
Definition: fsm_generator.h:360
virtual void reset(bool call_on_exit_state=false)
Reset the FSM to pre-started state.
Definition: fsm_generator.h:499
bool accepts(etl::message_id_t) const ETL_OVERRIDE
Does this FSM accept the message id? Yes, it accepts everything!
Definition: fsm_generator.h:455
void set_states(etl::ifsm_state **p_states, TSize size)
Set the states for the FSM.
Definition: fsm_generator.h:372
const ifsm_state & get_state() const
Gets a const reference to the current state interface.
Definition: fsm_generator.h:481
ifsm_state & get_state()
Gets a reference to the current state interface.
Definition: fsm_generator.h:472
bool is_started() const
Checks if the FSM has been started.
Definition: fsm_generator.h:490
Definition: hfsm.h:42
Interface class for FSM states.
Definition: fsm.h:198
void add_child_state(etl::ifsm_state &state)
Adds a child to this state. Only of use when part of an HFSM.
Definition: fsm_generator.h:258
void set_child_states(etl::ifsm_state **state_list, TSize size)
Adds a list of child states. Only of use when part of an HFSM.
Definition: fsm_generator.h:275
etl::fsm_state_id_t get_state_id() const
Gets the id for this state.
Definition: fsm_generator.h:249
ifsm_state(etl::fsm_state_id_t state_id_)
Constructor.
Definition: fsm_generator.h:292
virtual ~ifsm_state()
Destructor.
Definition: fsm_generator.h:304
This is the base of all message routers.
Definition: message_router_generator.h:121
Definition: message.h:69
Definition: message.h:84
#define ETL_ASSERT(b, e)
Definition: error_handler.h:316
Definition: exception.h:47
Definition: integral_limits.h:468
Defines a type that is as larger or larger than the specified type. Will return the specified type is...
Definition: largest_generator.h:352
bitset_ext
Definition: absolute.h:38
uint_least8_t message_id_t
Allow alternative type for message id.
Definition: message_types.h:40
uint_least8_t fsm_state_id_t
Allow alternative type for state id.
Definition: fsm.h:75