48 hfsm(etl::message_router_id_t
id)
60 void start(
bool call_on_enter_state =
true) ETL_OVERRIDE
69 p_state = p_first_state;
71 if (call_on_enter_state)
73 do_enters_result result = do_enters(ETL_NULLPTR, p_first_state,
true);
75 if (result.active_state_id != ifsm_state::No_State_Change)
81 p_state = state_list[result.active_state_id];
83 process_state_change(result.next_state_id);
87 if (have_changed_state(result.next_state_id))
90 p_state = state_list[result.next_state_id];
101 virtual void reset(
bool call_on_exit_state =
false) ETL_OVERRIDE
107 do_exits(ETL_NULLPTR, p_state);
110 p_state = ETL_NULLPTR;
120 size_t depth1 = get_depth(s1);
121 size_t depth2 = get_depth(s2);
126 s1 = adjust_depth(s1, depth1 - depth2);
130 s2 = adjust_depth(s2, depth2 - depth1);
146 static size_t get_depth(etl::ifsm_state* s)
150 while (s != ETL_NULLPTR)
162 static etl::ifsm_state* adjust_depth(etl::ifsm_state* s,
size_t offset)
176 struct do_enters_result
187 static do_enters_result do_enters(
const etl::ifsm_state* p_root, etl::ifsm_state* p_target,
bool activate_default_children)
189 ETL_ASSERT(p_target != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
192 if ((p_root != p_target) && (p_target->p_parent != ETL_NULLPTR))
194 if (p_target->p_parent != p_root)
197 do_enters_result result = do_enters(p_root, p_target->p_parent,
false);
200 if (result.active_state_id != ifsm_state::No_State_Change)
207 p_target->p_parent->p_active_child = p_target;
213 if (next_state != ifsm_state::No_State_Change)
219 if (activate_default_children)
221 while (p_target->p_default_child != ETL_NULLPTR)
223 p_target = p_target->p_default_child;
224 p_target->p_parent->p_active_child = p_target;
225 next_state = p_target->on_enter_state();
228 if (next_state != ifsm_state::No_State_Change)
238 return {next_state,
static_cast<fsm_state_id_t>(ifsm_state::No_State_Change)};
244 static void do_exits(
const etl::ifsm_state* p_root, etl::ifsm_state* p_source)
246 etl::ifsm_state* p_current = p_source;
249 while (p_current->p_active_child != ETL_NULLPTR)
251 p_current = p_current->p_active_child;
255 while (p_current != p_root)
257 p_current->on_exit_state();
258 p_current = p_current->p_parent;
267 if (is_self_transition(next_state_id))
269 p_state->on_exit_state();
270 next_state_id = p_state->on_enter_state();
273 while (have_changed_state(next_state_id))
275 ETL_ASSERT_OR_RETURN_VALUE(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception), p_state->get_state_id());
277 etl::ifsm_state* p_next_state = state_list[next_state_id];
278 etl::ifsm_state* p_root = common_ancestor(p_state, p_next_state);
280 do_exits(p_root, p_state);
282 do_enters_result result = do_enters(p_root, p_next_state,
true);
283 next_state_id = result.next_state_id;
285 if (result.active_state_id != ifsm_state::No_State_Change)
290 ETL_ASSERT(result.active_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
291 p_state = state_list[result.active_state_id];
292 ETL_ASSERT(result.next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
293 p_next_state = state_list[result.next_state_id];
295 else if (result.next_state_id != ifsm_state::No_State_Change)
299 ETL_ASSERT(result.next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
300 p_state = state_list[result.next_state_id];
301 p_next_state = state_list[result.next_state_id];
305 p_state = p_next_state;
309 return p_state->get_state_id();