48 hfsm(etl::message_router_id_t
id)
62 void start(
bool call_on_enter_state =
true) ETL_OVERRIDE
71 p_state = p_first_state;
73 if (call_on_enter_state)
75 do_enters_result result = do_enters(ETL_NULLPTR, p_first_state,
true);
77 if (result.active_state_id != ifsm_state::No_State_Change)
84 p_state = state_list[result.active_state_id];
86 process_state_change(result.next_state_id);
90 if (have_changed_state(result.next_state_id))
93 p_state = state_list[result.next_state_id];
105 virtual void reset(
bool call_on_exit_state =
false) ETL_OVERRIDE
111 do_exits(ETL_NULLPTR, p_state);
114 p_state = ETL_NULLPTR;
124 size_t depth1 = get_depth(s1);
125 size_t depth2 = get_depth(s2);
130 s1 = adjust_depth(s1, depth1 - depth2);
134 s2 = adjust_depth(s2, depth2 - depth1);
151 static size_t get_depth(etl::ifsm_state* s)
155 while (s != ETL_NULLPTR)
167 static etl::ifsm_state* adjust_depth(etl::ifsm_state* s,
size_t offset)
181 struct do_enters_result
192 static do_enters_result do_enters(
const etl::ifsm_state* p_root, etl::ifsm_state* p_target,
bool activate_default_children)
194 ETL_ASSERT(p_target != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
198 if ((p_root != p_target) && (p_target->p_parent != ETL_NULLPTR))
200 if (p_target->p_parent != p_root)
204 do_enters_result result = do_enters(p_root, p_target->p_parent,
false);
208 if (result.active_state_id != ifsm_state::No_State_Change)
215 p_target->p_parent->p_active_child = p_target;
222 if (next_state != ifsm_state::No_State_Change)
229 if (activate_default_children)
231 while (p_target->p_default_child != ETL_NULLPTR)
233 p_target = p_target->p_default_child;
234 p_target->p_parent->p_active_child = p_target;
235 next_state = p_target->on_enter_state();
239 if (next_state != ifsm_state::No_State_Change)
250 return {next_state,
static_cast<fsm_state_id_t>(ifsm_state::No_State_Change)};
256 static void do_exits(
const etl::ifsm_state* p_root, etl::ifsm_state* p_source)
258 etl::ifsm_state* p_current = p_source;
261 while (p_current->p_active_child != ETL_NULLPTR)
263 p_current = p_current->p_active_child;
267 while (p_current != p_root)
269 p_current->on_exit_state();
270 p_current = p_current->p_parent;
279 if (is_self_transition(next_state_id))
281 p_state->on_exit_state();
282 next_state_id = p_state->on_enter_state();
285 while (have_changed_state(next_state_id))
287 ETL_ASSERT_OR_RETURN_VALUE(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception), p_state->get_state_id());
289 etl::ifsm_state* p_next_state = state_list[next_state_id];
290 etl::ifsm_state* p_root = common_ancestor(p_state, p_next_state);
292 do_exits(p_root, p_state);
294 do_enters_result result = do_enters(p_root, p_next_state,
true);
295 next_state_id = result.next_state_id;
297 if (result.active_state_id != ifsm_state::No_State_Change)
303 ETL_ASSERT(result.active_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
304 p_state = state_list[result.active_state_id];
305 ETL_ASSERT(result.next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
306 p_next_state = state_list[result.next_state_id];
308 else if (result.next_state_id != ifsm_state::No_State_Change)
313 ETL_ASSERT(result.next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
314 p_state = state_list[result.next_state_id];
315 p_next_state = state_list[result.next_state_id];
319 p_state = p_next_state;
323 return p_state->get_state_id();