Embedded Template Library 1.0
Loading...
Searching...
No Matches
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 //***************************************************************************
193 //***************************************************************************
194 class fsm_not_started : public etl::fsm_exception
195 {
196 public:
197 fsm_not_started(string_type file_name_, numeric_type line_number_)
198 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:not started", ETL_FSM_FILE_ID"F"), file_name_, line_number_)
199 {
200 }
201 };
202
203 namespace private_fsm
204 {
205 template <typename T = void>
206 class ifsm_state_helper
207 {
208 public:
209
210 // Pass this whenever no state change is desired.
211 // The highest unsigned value of fsm_state_id_t.
212 static ETL_CONSTANT fsm_state_id_t No_State_Change = etl::integral_limits<fsm_state_id_t>::max;
213
214 // Pass this when this event also needs to be passed to the parent.
215 static ETL_CONSTANT fsm_state_id_t Pass_To_Parent = No_State_Change - 1U;
216
217 // Pass this when this event should trigger a self transition.
218 static ETL_CONSTANT fsm_state_id_t Self_Transition = No_State_Change - 2U;
219 };
220
221 template <typename T>
222 ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::No_State_Change;
223
224 template <typename T>
225 ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::Pass_To_Parent;
226
227 template <typename T>
228 ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::Self_Transition;
229 }
230
231 //***************************************************************************
233 //***************************************************************************
234 class ifsm_state : public private_fsm::ifsm_state_helper<>
235 {
236 public:
237
239 friend class etl::fsm;
240 friend class etl::hfsm;
241
242 using private_fsm::ifsm_state_helper<>::No_State_Change;
243 using private_fsm::ifsm_state_helper<>::Pass_To_Parent;
244 using private_fsm::ifsm_state_helper<>::Self_Transition;
245
246#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
247 template <typename, typename, etl::fsm_state_id_t, typename...>
248 friend class fsm_state;
249#else
250 /*[[[cog
251 import cog
252 cog.outl(" template <typename, typename, etl::fsm_state_id_t,")
253 cog.out(" ")
254 for n in range(1, int(Handlers)):
255 cog.out("typename, ")
256 if n % 4 == 0:
257 cog.outl("")
258 cog.out(" ")
259 cog.outl("typename>")
260 ]]]*/
261 /*[[[end]]]*/
262 friend class etl::fsm_state;
263#endif
264
265 //*******************************************
267 //*******************************************
269 {
270 return state_id;
271 }
272
273 //*******************************************
276 //*******************************************
278 {
279 ETL_ASSERT(state.p_parent == ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
280 state.p_parent = this;
281
282 if (p_default_child == ETL_NULLPTR)
283 {
284 p_active_child = &state;
285 p_default_child = &state;
286 }
287 }
288
289 //*******************************************
292 //*******************************************
293 template <typename TSize>
295 {
296 p_active_child = ETL_NULLPTR;
297 p_default_child = ETL_NULLPTR;
298
299 for (TSize i = 0; i < size; ++i)
300 {
301 ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
302 add_child_state(*state_list[i]);
303 }
304 }
305
306 protected:
307
308 //*******************************************
310 //*******************************************
312 : state_id(state_id_),
313 p_context(ETL_NULLPTR),
314 p_parent(ETL_NULLPTR),
315 p_active_child(ETL_NULLPTR),
316 p_default_child(ETL_NULLPTR)
317 {
318 }
319
320 //*******************************************
322 //*******************************************
323 virtual ~ifsm_state()
324 {
325 }
326
327 //*******************************************
328 etl::fsm& get_fsm_context() const
329 {
330 return *p_context;
331 }
332
333 private:
334
335 virtual fsm_state_id_t process_event(const etl::imessage& message) = 0;
336
337 virtual fsm_state_id_t on_enter_state() { return No_State_Change; } // By default, do nothing.
338 virtual void on_exit_state() {} // By default, do nothing.
339
340 //*******************************************
341 void set_fsm_context(etl::fsm& context)
342 {
343 p_context = &context;
344 }
345
346 // The state id.
347 const etl::fsm_state_id_t state_id;
348
349 // A pointer to the FSM context.
350 etl::fsm* p_context;
351
352 // A pointer to the parent.
353 ifsm_state* p_parent;
354
355 // A pointer to the active child.
356 ifsm_state* p_active_child;
357
358 // A pointer to the default active child.
359 ifsm_state* p_default_child;
360
361 // Disabled.
362 ifsm_state(const ifsm_state&);
363 ifsm_state& operator =(const ifsm_state&);
364 };
365
366 //***************************************************************************
368 //***************************************************************************
369 class fsm : public etl::imessage_router
370 {
371 public:
372
373 friend class etl::hfsm;
374 using imessage_router::receive;
375
376 //*******************************************
378 //*******************************************
379 fsm(etl::message_router_id_t id)
380 : imessage_router(id)
381 , p_state(ETL_NULLPTR)
382 , state_list(ETL_NULLPTR)
383 , number_of_states(0U)
384 {
385 }
386
387 //*******************************************
389 //*******************************************
390 template <typename TSize>
392 {
393 state_list = p_states;
394 number_of_states = etl::fsm_state_id_t(size);
395
396 ETL_ASSERT(number_of_states > 0, ETL_ERROR(etl::fsm_state_list_exception));
397 ETL_ASSERT(number_of_states < ifsm_state::No_State_Change, ETL_ERROR(etl::fsm_state_list_exception));
398
399 for (etl::fsm_state_id_t i = 0; i < size; ++i)
400 {
401 ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
402 ETL_ASSERT(state_list[i]->get_state_id() == i, ETL_ERROR(etl::fsm_state_list_order_exception));
403 state_list[i]->set_fsm_context(*this);
404 }
405 }
406
407 //*******************************************
412 //*******************************************
413 virtual void start(bool call_on_enter_state = true)
414 {
415 // Can only be started once.
416 if (p_state == ETL_NULLPTR)
417 {
418 p_state = state_list[0];
419 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
420
422 {
423 etl::fsm_state_id_t next_state_id;
425
426 do
427 {
428 p_last_state = p_state;
429 next_state_id = p_state->on_enter_state();
430 if (next_state_id != ifsm_state::No_State_Change)
431 {
432 ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
433 p_state = state_list[next_state_id];
434 }
435 } while (p_last_state != p_state);
436 }
437 }
438 }
439
440 //*******************************************
442 //*******************************************
443 void receive(const etl::imessage& message) ETL_OVERRIDE
444 {
445 if (is_started())
446 {
447 etl::fsm_state_id_t next_state_id = p_state->process_event(message);
448
449 if (have_changed_state(next_state_id))
450 {
451 ETL_ASSERT_OR_RETURN(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
452 etl::ifsm_state* p_next_state = state_list[next_state_id];
453
454 do
455 {
456 p_state->on_exit_state();
457 p_state = p_next_state;
458
459 next_state_id = p_state->on_enter_state();
460
461 if (have_changed_state(next_state_id))
462 {
463 ETL_ASSERT_OR_RETURN(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
464 p_next_state = state_list[next_state_id];
465 }
466 } while (p_next_state != p_state); // Have we changed state again?
467 }
468 else if (is_self_transition(next_state_id))
469 {
470 p_state->on_exit_state();
471 p_state->on_enter_state();
472 }
473 }
474 else
475 {
476 ETL_ASSERT_FAIL(ETL_ERROR(etl::fsm_not_started));
477 }
478 }
479
480 using imessage_router::accepts;
481
482 //*******************************************
485 //*******************************************
486 bool accepts(etl::message_id_t) const ETL_OVERRIDE
487 {
488 return true;
489 }
490
491 //*******************************************
493 //*******************************************
495 {
496 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
497 return p_state->get_state_id();
498 }
499
500 //*******************************************
502 //*******************************************
504 {
505 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
506 return *p_state;
507 }
508
509 //*******************************************
511 //*******************************************
512 const ifsm_state& get_state() const
513 {
514 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
515 return *p_state;
516 }
517
518 //*******************************************
520 //*******************************************
521 bool is_started() const
522 {
523 return p_state != ETL_NULLPTR;
524 }
525
526 //*******************************************
529 //*******************************************
530 virtual void reset(bool call_on_exit_state = false)
531 {
532 if ((p_state != ETL_NULLPTR) && call_on_exit_state)
533 {
534 p_state->on_exit_state();
535 }
536
537 p_state = ETL_NULLPTR;
538 }
539
540 //********************************************
541 ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
542 {
543 return false;
544 }
545
546 //********************************************
547 bool is_producer() const ETL_OVERRIDE
548 {
549 return true;
550 }
551
552 //********************************************
553 bool is_consumer() const ETL_OVERRIDE
554 {
555 return true;
556 }
557
558 private:
559
560 //********************************************
561 bool have_changed_state(etl::fsm_state_id_t next_state_id) const
562 {
563 return (next_state_id != p_state->get_state_id()) &&
564 (next_state_id != ifsm_state::No_State_Change) &&
565 (next_state_id != ifsm_state::Self_Transition);
566 }
567
568 //********************************************
569 bool is_self_transition(etl::fsm_state_id_t next_state_id) const
570 {
571 return (next_state_id == ifsm_state::Self_Transition);
572 }
573
574 etl::ifsm_state* p_state;
575 etl::ifsm_state** state_list;
576 etl::fsm_state_id_t number_of_states;
577 };
578
579 //*************************************************************************************************
580 // For C++17 and above.
581 //*************************************************************************************************
582#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
583 //***************************************************************************
584 // The definition for all types.
585 //***************************************************************************
586 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
587 class fsm_state : public ifsm_state
588 {
589 public:
590
591 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
592
593 fsm_state()
594 : ifsm_state(STATE_ID)
595 {
596 }
597
598 protected:
599
600 ~fsm_state()
601 {
602 }
603
604 TContext& get_fsm_context() const
605 {
606 return static_cast<TContext&>(ifsm_state::get_fsm_context());
607 }
608
609 private:
610
611 //********************************************
612 struct result_t
613 {
614 bool was_handled;
615 etl::fsm_state_id_t state_id;
616 };
617
618 //********************************************
619 etl::fsm_state_id_t process_event(const etl::imessage& message)
620 {
621 etl::fsm_state_id_t new_state_id;
622
623 const bool was_handled = (process_event_type<TMessageTypes>(message, new_state_id) || ...);
624
625 if (!was_handled || (new_state_id == Pass_To_Parent))
626 {
627 new_state_id = (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
628 }
629
630 return new_state_id;
631 }
632
633 //********************************************
634 template <typename TMessage>
635 bool process_event_type(const etl::imessage& msg, etl::fsm_state_id_t& new_state_id)
636 {
637 if (TMessage::ID == msg.get_message_id())
638 {
639 new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const TMessage&>(msg));
640 return true;
641 }
642 else
643 {
644 return false;
645 }
646 }
647 };
648
650 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
651 ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::STATE_ID;
652
653#else
654//*************************************************************************************************
655// For C++14 and below.
656//*************************************************************************************************
657 /*[[[cog
658 import cog
659 ################################################
660 # The first definition for all of the events.
661 ################################################
662 cog.outl("//***************************************************************************")
663 cog.outl("// The definition for all %s message types." % Handlers)
664 cog.outl("//***************************************************************************")
665 cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, ")
666 cog.out(" ")
667 for n in range(1, int(Handlers)):
668 cog.out("typename T%s = void, " % n)
669 if n % 4 == 0:
670 cog.outl("")
671 cog.out(" ")
672 cog.outl("typename T%s = void>" % Handlers)
673 cog.outl("class fsm_state : public ifsm_state")
674 cog.outl("{")
675 cog.outl("public:")
676 cog.outl("")
677 cog.outl(" static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;")
678 cog.outl("")
679 cog.outl(" fsm_state()")
680 cog.outl(" : ifsm_state(STATE_ID)")
681 cog.outl(" {")
682 cog.outl(" }")
683 cog.outl("")
684 cog.outl("protected:")
685 cog.outl("")
686 cog.outl(" ~fsm_state()")
687 cog.outl(" {")
688 cog.outl(" }")
689 cog.outl("")
690 cog.outl(" TContext& get_fsm_context() const")
691 cog.outl(" {")
692 cog.outl(" return static_cast<TContext&>(ifsm_state::get_fsm_context());")
693 cog.outl(" }")
694 cog.outl("")
695 cog.outl("private:")
696 cog.outl("")
697 cog.outl(" etl::fsm_state_id_t process_event(const etl::imessage& message)")
698 cog.outl(" {")
699 cog.outl(" etl::fsm_state_id_t new_state_id;")
700 cog.outl(" etl::message_id_t event_id = message.get_message_id();")
701 cog.outl("")
702 cog.outl(" switch (event_id)")
703 cog.outl(" {")
704 for n in range(1, int(Handlers) + 1):
705 cog.out(" case T%d::ID:" % n)
706 cog.out(" new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T%d&>(message));" % n)
707 cog.outl(" break;")
708 cog.out(" default:")
709 cog.out(" new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);")
710 cog.outl(" break;")
711 cog.outl(" }")
712 cog.outl("")
713 cog.outl(" return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);")
714 cog.outl(" }")
715 cog.outl("};")
716
717 ####################################
718 # All of the other specialisations.
719 ####################################
720 for n in range(int(Handlers) - 1, 0, -1):
721 cog.outl("")
722 cog.outl("//***************************************************************************")
723 if n == 1:
724 cog.outl("// Specialisation for %d message type." % n)
725 else:
726 cog.outl("// Specialisation for %d message types." % n)
727 cog.outl("//***************************************************************************")
728 cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, ")
729 cog.out(" ")
730 for t in range(1, n):
731 cog.out("typename T%d, " % t)
732 if t % 4 == 0:
733 cog.outl("")
734 cog.out(" ")
735 cog.outl("typename T%d>" % n)
736 cog.out("class fsm_state<TContext, TDerived, STATE_ID_, ")
737 for t in range(1, n + 1):
738 cog.out("T%d, " % t)
739 if t % 16 == 0:
740 cog.outl("")
741 cog.out(" ")
742 for t in range(n + 1, int(Handlers)):
743 cog.out("void, ")
744 if t % 16 == 0:
745 cog.outl("")
746 cog.out(" ")
747 cog.outl("void> : public ifsm_state")
748 cog.outl("{")
749 cog.outl("public:")
750 cog.outl("")
751 cog.outl(" static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;")
752 cog.outl("")
753 cog.outl(" fsm_state()")
754 cog.outl(" : ifsm_state(STATE_ID)")
755 cog.outl(" {")
756 cog.outl(" }")
757 cog.outl("")
758 cog.outl("protected:")
759 cog.outl("")
760 cog.outl(" ~fsm_state()")
761 cog.outl(" {")
762 cog.outl(" }")
763 cog.outl("")
764 cog.outl(" TContext& get_fsm_context() const")
765 cog.outl(" {")
766 cog.outl(" return static_cast<TContext&>(ifsm_state::get_fsm_context());")
767 cog.outl(" }")
768 cog.outl("")
769 cog.outl("private:")
770 cog.outl("")
771 cog.outl(" etl::fsm_state_id_t process_event(const etl::imessage& message)")
772 cog.outl(" {")
773 cog.outl(" etl::fsm_state_id_t new_state_id;")
774 cog.outl(" etl::message_id_t event_id = message.get_message_id();")
775 cog.outl("")
776 cog.outl(" switch (event_id)")
777 cog.outl(" {")
778 for n in range(1, n + 1):
779 cog.out(" case T%d::ID:" % n)
780 cog.out(" new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T%d&>(message));" % n)
781 cog.outl(" break;")
782 cog.out(" default:")
783 cog.out(" new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);")
784 cog.outl(" break;")
785 cog.outl(" }")
786 cog.outl("")
787 cog.outl(" return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);")
788 cog.outl(" }")
789 cog.outl("};")
790 ####################################
791 # Specialisation for zero messages.
792 ####################################
793 cog.outl("")
794 cog.outl("//***************************************************************************")
795 cog.outl("// Specialisation for 0 message types.")
796 cog.outl("//***************************************************************************")
797 cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_>")
798 cog.out("class fsm_state<TContext, TDerived, STATE_ID_, ")
799 for t in range(1, int(Handlers)):
800 cog.out("void, ")
801 if t % 16 == 0:
802 cog.outl("")
803 cog.out(" ")
804 cog.outl("void> : public ifsm_state")
805 cog.outl("{")
806 cog.outl("public:")
807 cog.outl("")
808 cog.outl(" static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;")
809 cog.outl("")
810 cog.outl(" fsm_state()")
811 cog.outl(" : ifsm_state(STATE_ID)")
812 cog.outl(" {")
813 cog.outl(" }")
814 cog.outl("")
815 cog.outl("protected:")
816 cog.outl("")
817 cog.outl(" ~fsm_state()")
818 cog.outl(" {")
819 cog.outl(" }")
820 cog.outl("")
821 cog.outl(" TContext& get_fsm_context() const")
822 cog.outl(" {")
823 cog.outl(" return static_cast<TContext&>(ifsm_state::get_fsm_context());")
824 cog.outl(" }")
825 cog.outl("private:")
826 cog.outl("")
827 cog.outl(" etl::fsm_state_id_t process_event(const etl::imessage& message)")
828 cog.outl(" {")
829 cog.outl(" return p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);")
830 cog.outl(" }")
831 cog.outl("};")
832
833 cog.outl("")
834 cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, ")
835 cog.out(" ")
836 for n in range(1, int(Handlers)):
837 cog.out("typename T%s, " % n)
838 if n % 4 == 0:
839 cog.outl("")
840 cog.out(" ")
841 cog.outl("typename T%s>" % Handlers)
842 cog.out("ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, ")
843 for n in range(1, int(Handlers)):
844 cog.out("T%s, " % n)
845 cog.outl("T%s>::STATE_ID;" % Handlers)
846 ]]]*/
847 /*[[[end]]]*/
848#endif
849}
850
851#include "private/minmax_pop.h"
852
853#endif
Base exception class for FSM.
Definition fsm.h:99
Exception for message received but not started.
Definition fsm.h:176
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:640
The FSM class.
Definition fsm.h:344
etl::fsm_state_id_t get_state_id() const
Gets the current state id.
Definition fsm_generator.h:494
void receive(const etl::imessage &message) ETL_OVERRIDE
Top level message handler for the FSM.
Definition fsm_generator.h:443
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:413
fsm(etl::message_router_id_t id)
Constructor.
Definition fsm_generator.h:379
virtual void reset(bool call_on_exit_state=false)
Reset the FSM to pre-started state.
Definition fsm_generator.h:530
bool accepts(etl::message_id_t) const ETL_OVERRIDE
Does this FSM accept the message id? Yes, it accepts everything!
Definition fsm_generator.h:486
void set_states(etl::ifsm_state **p_states, TSize size)
Set the states for the FSM.
Definition fsm_generator.h:391
const ifsm_state & get_state() const
Gets a const reference to the current state interface.
Definition fsm_generator.h:512
ifsm_state & get_state()
Gets a reference to the current state interface.
Definition fsm_generator.h:503
bool is_started() const
Checks if the FSM has been started.
Definition fsm_generator.h:521
Definition hfsm.h:42
Interface class for FSM states.
Definition fsm.h:216
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:277
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:294
etl::fsm_state_id_t get_state_id() const
Gets the id for this state.
Definition fsm_generator.h:268
ifsm_state(etl::fsm_state_id_t state_id_)
Constructor.
Definition fsm_generator.h:311
virtual ~ifsm_state()
Destructor.
Definition fsm_generator.h:323
This is the base of all message routers.
Definition message_router_generator.h:123
Definition message.h:73
Definition message.h:91
#define ETL_ASSERT(b, e)
Definition error_handler.h:316
Definition exception.h:47
Definition integral_limits.h:516
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
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1187
uint_least8_t fsm_state_id_t
Allow alternative type for state id.
Definition fsm.h:75
pair holds two objects of arbitrary type
Definition utility.h:164