34#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
63#ifndef ETL_FSM_INCLUDED
64#define ETL_FSM_INCLUDED
72#include "message_router.h"
89#if !defined(ETL_FSM_STATE_ID_TYPE)
96 typedef typename etl::larger_type<etl::message_id_t>::type fsm_internal_id_t;
98#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION)
124 fsm_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
125 : etl::
exception(reason_, file_name_, line_number_)
138 : etl::
fsm_exception(ETL_ERROR_TEXT(
"fsm:null state", ETL_FSM_FILE_ID
"A"), file_name_, line_number_)
151 : etl::
fsm_exception(ETL_ERROR_TEXT(
"fsm:state id", ETL_FSM_FILE_ID
"B"), file_name_, line_number_)
164 : etl::
fsm_exception(ETL_ERROR_TEXT(
"fsm:state list", ETL_FSM_FILE_ID
"C"), file_name_, line_number_)
177 : etl::
fsm_exception(ETL_ERROR_TEXT(
"fsm:state list order", ETL_FSM_FILE_ID
"D"), file_name_, line_number_)
189 : etl::
fsm_exception(ETL_ERROR_TEXT(
"fsm:not started", ETL_FSM_FILE_ID
"F"), file_name_, line_number_)
202 : etl::
fsm_exception(ETL_ERROR_TEXT(
"fsm:reentrant calls to start/receive/etc. forbidden", ETL_FSM_FILE_ID
"G"), file_name_, line_number_)
207 namespace private_fsm
209 template <
typename T =
void>
210 class ifsm_state_helper
216 static ETL_CONSTANT
fsm_state_id_t No_State_Change = etl::integral_limits<fsm_state_id_t>::max;
219 static ETL_CONSTANT
fsm_state_id_t Pass_To_Parent = No_State_Change - 1U;
222 static ETL_CONSTANT
fsm_state_id_t Self_Transition = No_State_Change - 2U;
225 template <
typename T>
226 ETL_CONSTANT
fsm_state_id_t ifsm_state_helper<T>::No_State_Change;
228 template <
typename T>
231 template <
typename T>
232 ETL_CONSTANT
fsm_state_id_t ifsm_state_helper<T>::Self_Transition;
235 template <
size_t Id,
typename...>
struct check_ids : etl::true_type
239 template <
size_t Id,
typename TState0,
typename... TRest>
240 struct check_ids<Id, TState0, TRest...>
241 : etl::integral_constant<bool, (TState0::STATE_ID == Id) && private_fsm::check_ids<Id + 1, TRest...>::value>
250 class fsm_reentrancy_guard
258 : is_locked(transition_guard_flag)
293 template <
typename... TStates>
300 ETL_STATIC_ASSERT((private_fsm::check_ids<0, TStates...>::value),
"State IDs must be 0..N-1 and in order");
301 ETL_STATIC_ASSERT(
sizeof...(TStates) > 0,
"At least one state is required");
302 ETL_STATIC_ASSERT(
sizeof...(TStates) < private_fsm::ifsm_state_helper<>::No_State_Change,
"State IDs mst be less than ifsm_state::No_State_Change");
307 static ETL_CONSTEXPR
size_t size()
309 return sizeof...(TStates);
315 template <
typename TState>
324 template <
typename TState>
325 const TState&
get()
const
335 etl::ifsm_state** get_state_list()
341 etl::tuple<TStates...> storage{};
357 friend class etl::hfsm;
359 using private_fsm::ifsm_state_helper<>::No_State_Change;
360 using private_fsm::ifsm_state_helper<>::Pass_To_Parent;
361 using private_fsm::ifsm_state_helper<>::Self_Transition;
363#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION)
365 friend class fsm_state;
379 friend class etl::fsm_state;
397 state.p_parent =
this;
399 if (p_default_child == ETL_NULLPTR)
401 p_default_child = &state;
409 template <
typename TSize>
412 p_active_child = ETL_NULLPTR;
413 p_default_child = ETL_NULLPTR;
415 for (TSize i = 0; i <
size; ++i)
428 : state_id(state_id_),
429 p_context(ETL_NULLPTR),
430 p_parent(ETL_NULLPTR),
431 p_active_child(ETL_NULLPTR),
432 p_default_child(ETL_NULLPTR)
453 virtual fsm_state_id_t on_enter_state() {
return No_State_Change; }
454 virtual void on_exit_state() {}
457 void set_fsm_context(etl::fsm& context)
459 p_context = &context;
485 class fsm :
public etl::imessage_router
489 friend class etl::hfsm;
490 using imessage_router::receive;
495 fsm(etl::message_router_id_t
id)
496 : imessage_router(id)
497 , p_state(ETL_NULLPTR)
498 , state_list(ETL_NULLPTR)
499 , number_of_states(0U)
500 , is_processing_state_change(false)
508 template <
typename TSize>
511 state_list = p_states;
521 state_list[i]->set_fsm_context(*
this);
530 template <
typename... TStates>
531 void set_states(etl::fsm_state_pack<TStates...>& state_pack)
533 state_list = state_pack.get_state_list();
538 state_list[i]->set_fsm_context(*
this);
549 virtual void start(
bool call_on_enter_state =
true)
556 p_state = state_list[0];
559 if (call_on_enter_state)
566 p_last_state = p_state;
567 next_state_id = p_state->on_enter_state();
568 if (next_state_id != ifsm_state::No_State_Change)
571 p_state = state_list[next_state_id];
573 }
while (p_last_state != p_state);
589 process_state_change(next_state_id);
606 return process_state_change(new_state_id);
610 return ifsm_state::No_State_Change;
614 using imessage_router::accepts;
631 return p_state->get_state_id();
657 return p_state != ETL_NULLPTR;
664 virtual void reset(
bool call_on_exit_state =
false)
670 p_state->on_exit_state();
673 p_state = ETL_NULLPTR;
677 ETL_DEPRECATED
bool is_null_router() const ETL_OVERRIDE
683 bool is_producer() const ETL_OVERRIDE
689 bool is_consumer() const ETL_OVERRIDE
699 return (next_state_id != p_state->get_state_id()) &&
700 (next_state_id != ifsm_state::No_State_Change) &&
701 (next_state_id != ifsm_state::Self_Transition);
707 return (next_state_id == ifsm_state::Self_Transition);
715 if (is_self_transition(next_state_id))
717 p_state->on_exit_state();
718 next_state_id = p_state->on_enter_state();
721 if (have_changed_state(next_state_id))
723 ETL_ASSERT_OR_RETURN_VALUE(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception), p_state->get_state_id());
724 etl::ifsm_state* p_next_state = state_list[next_state_id];
728 p_state->on_exit_state();
729 p_state = p_next_state;
731 next_state_id = p_state->on_enter_state();
733 if (have_changed_state(next_state_id))
735 ETL_ASSERT_OR_RETURN_VALUE(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception), p_state->get_state_id());
736 p_next_state = state_list[next_state_id];
738 }
while (p_next_state != p_state);
741 return p_state->get_state_id();
744 etl::ifsm_state* p_state;
745 etl::ifsm_state** state_list;
747 bool is_processing_state_change;
753#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION)
757 template <
typename TContext,
typename TDerived,
etl::fsm_state_id_t STATE_ID_,
typename... TMessageTypes>
775 TContext& get_fsm_context()
const
777 return static_cast<TContext&
>(ifsm_state::get_fsm_context());
794 const bool was_handled = (process_event_type<TMessageTypes>(message, new_state_id) || ...);
796 if (!was_handled || (new_state_id == Pass_To_Parent))
798 new_state_id = (p_parent !=
nullptr) ? p_parent->process_event(message) :
static_cast<TDerived*
>(
this)->on_event_unknown(message);
805 template <
typename TMessage>
808 if (TMessage::ID == msg.get_message_id())
810 new_state_id =
static_cast<TDerived*
>(
this)->on_event(
static_cast<const TMessage&
>(msg));
821 template <
typename TContext,
typename TDerived,
etl::fsm_state_id_t STATE_ID_,
typename... TMessageTypes>
Base exception class for FSM.
Definition fsm.h:102
Exception for message received but not started.
Definition fsm.h:167
Exception for null state pointer.
Definition fsm.h:115
Exception for call to receive/start/etc. while receive/start/etc. is already happening....
Definition fsm.h:180
Exception for invalid state id.
Definition fsm.h:128
Exception for incompatible state list.
Definition fsm.h:141
Exception for incompatible order state list.
Definition fsm.h:154
The FSM class.
Definition fsm.h:460
etl::fsm_state_id_t get_state_id() const
Gets the current state id.
Definition fsm.h:602
void receive(const etl::imessage &message) ETL_OVERRIDE
Top level message handler for the FSM.
Definition fsm_generator.h:581
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:549
fsm(etl::message_router_id_t id)
Constructor.
Definition fsm_generator.h:495
virtual void reset(bool call_on_exit_state=false)
Reset the FSM to pre-started state.
Definition fsm_generator.h:664
bool accepts(etl::message_id_t) const ETL_OVERRIDE
Does this FSM accept the message id? Yes, it accepts everything!
Definition fsm_generator.h:620
etl::fsm_state_id_t transition_to(etl::fsm_state_id_t new_state_id)
Invoke a state transition.
Definition fsm_generator.h:600
void set_states(etl::ifsm_state **p_states, TSize size)
Set the states for the FSM From a pointer to etl::ifsm_state and size.
Definition fsm_generator.h:509
const ifsm_state & get_state() const
Gets a const reference to the current state interface.
Definition fsm_generator.h:646
ifsm_state & get_state()
Gets a reference to the current state interface.
Definition fsm_generator.h:637
bool is_started() const
Checks if the FSM has been started.
Definition fsm.h:629
Interface class for FSM states.
Definition fsm.h:333
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:394
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:410
etl::fsm_state_id_t get_state_id() const
Gets the id for this state.
Definition fsm_generator.h:385
ifsm_state(etl::fsm_state_id_t state_id_)
Constructor.
Definition fsm_generator.h:427
virtual ~ifsm_state()
Destructor.
Definition fsm_generator.h:439
friend class etl::fsm
Allows ifsm_state functions to be private.
Definition fsm.h:337
RAII detection mechanism to catch reentrant calls to methods that might transition the state machine ...
Definition fsm.h:232
~fsm_reentrancy_guard() ETL_NOEXCEPT
Destructor. Releases lock on reentrancy.
Definition fsm_generator.h:268
fsm_reentrancy_guard(bool &transition_guard_flag)
Constructor. Checks if another method has locked reentrancy.
Definition fsm_generator.h:257
#define ETL_ASSERT(b, e)
Definition error_handler.h:356
Definition exception.h:47
bitset_ext
Definition absolute.h:39
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
T & get(array< T, Size > &a)
Definition array.h:1216
uint_least8_t fsm_state_id_t
Allow alternative type for state id.
Definition fsm.h:78