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
189 : next_state_id(next_state_id_)
190 , active_state_id(active_state_id_)
198 static do_enters_result do_enters(
const etl::ifsm_state* p_root, etl::ifsm_state* p_target,
bool activate_default_children)
200 ETL_ASSERT(p_target != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
204 if ((p_root != p_target) && (p_target->p_parent != ETL_NULLPTR))
206 if (p_target->p_parent != p_root)
210 do_enters_result result = do_enters(p_root, p_target->p_parent,
false);
214 if (result.active_state_id != ifsm_state::No_State_Change)
221 p_target->p_parent->p_active_child = p_target;
228 if (next_state != ifsm_state::No_State_Change)
230 return do_enters_result(next_state, p_target->
get_state_id());
235 if (activate_default_children)
237 while (p_target->p_default_child != ETL_NULLPTR)
239 p_target = p_target->p_default_child;
240 p_target->p_parent->p_active_child = p_target;
241 next_state = p_target->on_enter_state();
245 if (next_state != ifsm_state::No_State_Change)
247 return do_enters_result(next_state, p_target->
get_state_id());
256 return do_enters_result(next_state,
static_cast<fsm_state_id_t>(ifsm_state::No_State_Change));
262 static void do_exits(
const etl::ifsm_state* p_root, etl::ifsm_state* p_source)
264 etl::ifsm_state* p_current = p_source;
267 while (p_current->p_active_child != ETL_NULLPTR)
269 p_current = p_current->p_active_child;
273 while (p_current != p_root)
275 p_current->on_exit_state();
276 p_current = p_current->p_parent;
285 if (is_self_transition(next_state_id))
287 p_state->on_exit_state();
288 next_state_id = p_state->on_enter_state();
291 while (have_changed_state(next_state_id))
293 ETL_ASSERT_OR_RETURN_VALUE(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception), p_state->get_state_id());
295 etl::ifsm_state* p_next_state = state_list[next_state_id];
296 etl::ifsm_state* p_root = common_ancestor(p_state, p_next_state);
298 do_exits(p_root, p_state);
300 do_enters_result result = do_enters(p_root, p_next_state,
true);
301 next_state_id = result.next_state_id;
303 if (result.active_state_id != ifsm_state::No_State_Change)
309 ETL_ASSERT(result.active_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
310 p_state = state_list[result.active_state_id];
311 ETL_ASSERT(result.next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
312 p_next_state = state_list[result.next_state_id];
314 else if (result.next_state_id != ifsm_state::No_State_Change)
319 ETL_ASSERT(result.next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
320 p_state = state_list[result.next_state_id];
321 p_next_state = state_list[result.next_state_id];
325 p_state = p_next_state;
329 return p_state->get_state_id();