From 7f2ea864e00ea45597f39dbf47d7d699abaddc65 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 24 Apr 2021 09:25:39 +0100 Subject: [PATCH] Minor changes & renames --- include/etl/fsm.h | 87 ++++++++++++++++++-------- include/etl/generators/fsm_generator.h | 82 +++++++++++++++++------- include/etl/hfsm.h | 14 +++-- test/test_fsm.cpp | 2 +- test/test_hfsm.cpp | 27 ++++---- 5 files changed, 145 insertions(+), 67 deletions(-) diff --git a/include/etl/fsm.h b/include/etl/fsm.h index 4149d802..d3f09847 100644 --- a/include/etl/fsm.h +++ b/include/etl/fsm.h @@ -153,13 +153,13 @@ namespace etl }; //*************************************************************************** - /// Exception for forbidden state changes. + /// Exception for forbidden state chages. //*************************************************************************** - class fsm_state_enter_state_change_forbidden : public etl::fsm_exception + class fsm_state_composite_state_change_forbidden : public etl::fsm_exception { public: - fsm_state_enter_state_change_forbidden(string_type file_name_, numeric_type line_number_) - : etl::fsm_exception(ETL_ERROR_TEXT("fsm:enter state change in composite state forbidden", ETL_FSM_FILE_ID"E"), file_name_, line_number_) + fsm_state_composite_state_change_forbidden(string_type file_name_, numeric_type line_number_) + : etl::fsm_exception(ETL_ERROR_TEXT("fsm:change in composite state forbidden", ETL_FSM_FILE_ID"E"), file_name_, line_number_) { } }; @@ -173,16 +173,16 @@ namespace etl // Pass this whenever no state change is desired. Specifically cast to // Highest unsigned value of fsm_state_id_t. - static const fsm_state_id_t NO_CHANGE = static_cast(-1); + static const fsm_state_id_t No_State_Change = static_cast(-1); /// Allows ifsm_state functions to be private. friend class etl::fsm; friend class etl::hfsm; template + typename, typename, typename, typename, + typename, typename, typename, typename, + typename, typename, typename, typename, + typename, typename, typename, typename > friend class etl::fsm_state; //******************************************* @@ -196,21 +196,56 @@ namespace etl //******************************************* /// Adds a child to this state. //******************************************* - void add_child(etl::ifsm_state& state) + void add_child_state(etl::ifsm_state& state) { ETL_ASSERT(state.p_parent == ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception)); state.p_parent = this; + + if (p_default_child == ETL_NULLPTR) + { + p_active_child = &state; + p_default_child = &state; + } } //******************************************* - /// Adds the initial child to this state. + /// Adds a list of child states. //******************************************* - void add_initial_child(etl::ifsm_state& state) + template + void set_child_states(etl::ifsm_state** state_list, TSize size) { - ETL_ASSERT(p_default_active_child == ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception)); - add_child(state); - p_active_child = &state; - p_default_active_child = &state; + p_active_child = ETL_NULLPTR; + p_default_child = ETL_NULLPTR; + + for (TSize i = 0; i < size; ++i) + { + ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception)); + add_child_state(*state_list[i]); + } + } + + //******************************************* + /// Get the parent state for this state. + //******************************************* + etl::ifsm_state* get_parent_state() const + { + return p_parent; + } + + //******************************************* + /// Get the active child state for this state. + //******************************************* + etl::ifsm_state* get_active_child_state() const + { + return p_active_child; + } + + //******************************************* + /// Get the default child state for this state. + //******************************************* + etl::ifsm_state* get_default_child_state() const + { + return p_default_child; } protected: @@ -223,7 +258,7 @@ namespace etl p_context(ETL_NULLPTR), p_parent(ETL_NULLPTR), p_active_child(ETL_NULLPTR), - p_default_active_child(ETL_NULLPTR) + p_default_child(ETL_NULLPTR) { } @@ -244,7 +279,7 @@ namespace etl virtual fsm_state_id_t process_event(const etl::imessage& message) = 0; - virtual fsm_state_id_t on_enter_state() { return NO_CHANGE; } // By default, do nothing. + virtual fsm_state_id_t on_enter_state() { return No_State_Change; } // By default, do nothing. virtual void on_exit_state() {} // By default, do nothing. //******************************************* @@ -266,7 +301,7 @@ namespace etl ifsm_state* p_active_child; // A pointer to the default active child. - ifsm_state* p_default_active_child; + ifsm_state* p_default_child; // Disabled. ifsm_state(const ifsm_state&); @@ -304,7 +339,7 @@ namespace etl number_of_states = etl::fsm_state_id_t(size); ETL_ASSERT(number_of_states > 0, ETL_ERROR(etl::fsm_state_list_exception)); - ETL_ASSERT(number_of_states < ifsm_state::NO_CHANGE, ETL_ERROR(etl::fsm_state_list_exception)); + ETL_ASSERT(number_of_states < ifsm_state::No_State_Change, ETL_ERROR(etl::fsm_state_list_exception)); for (etl::fsm_state_id_t i = 0; i < size; ++i) { @@ -337,7 +372,7 @@ namespace etl { p_last_state = p_state; next_state_id = p_state->on_enter_state(); - if (next_state_id != ifsm_state::NO_CHANGE) + if (next_state_id != ifsm_state::No_State_Change) { ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception)); p_state = state_list[next_state_id]; @@ -354,7 +389,7 @@ namespace etl { etl::fsm_state_id_t next_state_id = p_state->process_event(message); - if(next_state_id != ifsm_state::NO_CHANGE) + if(next_state_id != ifsm_state::No_State_Change) { ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception)); etl::ifsm_state* p_next_state = state_list[next_state_id]; @@ -368,7 +403,7 @@ namespace etl p_state = p_next_state; next_state_id = p_state->on_enter_state(); - if(next_state_id != ifsm_state::NO_CHANGE) + if(next_state_id != ifsm_state::No_State_Change) { ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception)); p_next_state = state_list[next_state_id]; @@ -467,9 +502,9 @@ namespace etl // The definition for all 16 message types. //*************************************************************************** template class fsm_state : public ifsm_state { diff --git a/include/etl/generators/fsm_generator.h b/include/etl/generators/fsm_generator.h index 12a665c3..96ec2105 100644 --- a/include/etl/generators/fsm_generator.h +++ b/include/etl/generators/fsm_generator.h @@ -164,11 +164,14 @@ namespace etl } }; - class fsm_state_enter_state_change_forbidden : public etl::fsm_exception + //*************************************************************************** + /// Exception for forbidden state chages. + //*************************************************************************** + class fsm_state_composite_state_change_forbidden : public etl::fsm_exception { public: - fsm_state_enter_state_change_forbidden(string_type file_name_, numeric_type line_number_) - : etl::fsm_exception(ETL_ERROR_TEXT("fsm:enter state change in composite state forbidden", ETL_FSM_FILE_ID"E"), file_name_, line_number_) + fsm_state_composite_state_change_forbidden(string_type file_name_, numeric_type line_number_) + : etl::fsm_exception(ETL_ERROR_TEXT("fsm:change in composite state forbidden", ETL_FSM_FILE_ID"E"), file_name_, line_number_) { } }; @@ -182,16 +185,16 @@ namespace etl // Pass this whenever no state change is desired. Specifically cast to // Highest unsigned value of fsm_state_id_t. - static const fsm_state_id_t NO_CHANGE = static_cast(-1); + static const fsm_state_id_t No_State_Change = static_cast(-1); /// Allows ifsm_state functions to be private. friend class etl::fsm; friend class etl::hfsm; template + typename, typename, typename, typename, + typename, typename, typename, typename, + typename, typename, typename, typename, + typename, typename, typename, typename > friend class etl::fsm_state; //******************************************* @@ -205,21 +208,56 @@ namespace etl //******************************************* /// Adds a child to this state. //******************************************* - void add_child(etl::ifsm_state& state) + void add_child_state(etl::ifsm_state& state) { ETL_ASSERT(state.p_parent == ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception)); state.p_parent = this; + + if (p_default_child == ETL_NULLPTR) + { + p_active_child = &state; + p_default_child = &state; + } } //******************************************* - /// Adds the initial child to this state. + /// Adds a list of child states. //******************************************* - void add_initial_child(etl::ifsm_state& state) + template + void set_child_states(etl::ifsm_state** state_list, TSize size) { - ETL_ASSERT(p_default_active_child == ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception)); - add_child(state); - p_active_child = &state; - p_default_active_child = &state; + p_active_child = ETL_NULLPTR; + p_default_child = ETL_NULLPTR; + + for (TSize i = 0; i < size; ++i) + { + ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception)); + add_child_state(*state_list[i]); + } + } + + //******************************************* + /// Get the parent state for this state. + //******************************************* + etl::ifsm_state* get_parent_state() const + { + return p_parent; + } + + //******************************************* + /// Get the active child state for this state. + //******************************************* + etl::ifsm_state* get_active_child_state() const + { + return p_active_child; + } + + //******************************************* + /// Get the default child state for this state. + //******************************************* + etl::ifsm_state* get_default_child_state() const + { + return p_default_child; } protected: @@ -232,7 +270,7 @@ namespace etl p_context(ETL_NULLPTR), p_parent(ETL_NULLPTR), p_active_child(ETL_NULLPTR), - p_default_active_child(ETL_NULLPTR) + p_default_child(ETL_NULLPTR) { } @@ -253,7 +291,7 @@ namespace etl virtual fsm_state_id_t process_event(const etl::imessage& message) = 0; - virtual fsm_state_id_t on_enter_state() { return NO_CHANGE; } // By default, do nothing. + virtual fsm_state_id_t on_enter_state() { return No_State_Change; } // By default, do nothing. virtual void on_exit_state() {} // By default, do nothing. //******************************************* @@ -275,7 +313,7 @@ namespace etl ifsm_state* p_active_child; // A pointer to the default active child. - ifsm_state* p_default_active_child; + ifsm_state* p_default_child; // Disabled. ifsm_state(const ifsm_state&); @@ -313,7 +351,7 @@ namespace etl number_of_states = etl::fsm_state_id_t(size); ETL_ASSERT(number_of_states > 0, ETL_ERROR(etl::fsm_state_list_exception)); - ETL_ASSERT(number_of_states < ifsm_state::NO_CHANGE, ETL_ERROR(etl::fsm_state_list_exception)); + ETL_ASSERT(number_of_states < ifsm_state::No_State_Change, ETL_ERROR(etl::fsm_state_list_exception)); for (etl::fsm_state_id_t i = 0; i < size; ++i) { @@ -346,7 +384,7 @@ namespace etl { p_last_state = p_state; next_state_id = p_state->on_enter_state(); - if (next_state_id != ifsm_state::NO_CHANGE) + if (next_state_id != ifsm_state::No_State_Change) { ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception)); p_state = state_list[next_state_id]; @@ -363,7 +401,7 @@ namespace etl { etl::fsm_state_id_t next_state_id = p_state->process_event(message); - if(next_state_id != ifsm_state::NO_CHANGE) + if(next_state_id != ifsm_state::No_State_Change) { ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception)); etl::ifsm_state* p_next_state = state_list[next_state_id]; @@ -377,7 +415,7 @@ namespace etl p_state = p_next_state; next_state_id = p_state->on_enter_state(); - if(next_state_id != ifsm_state::NO_CHANGE) + if(next_state_id != ifsm_state::No_State_Change) { ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception)); p_next_state = state_list[next_state_id]; diff --git a/include/etl/hfsm.h b/include/etl/hfsm.h index 2738a6a2..f4c1c5b1 100644 --- a/include/etl/hfsm.h +++ b/include/etl/hfsm.h @@ -36,6 +36,8 @@ namespace etl //*************************************************************************** /// The HFSM class. + /// Builds on the FSM class by overriding the receive function and adding + /// state hierarchy walking functions. //*************************************************************************** class hfsm : public etl::fsm { @@ -58,7 +60,7 @@ namespace etl { etl::fsm_state_id_t next_state_id = p_state->process_event(message); - if (next_state_id != ifsm_state::NO_CHANGE) + if (next_state_id != ifsm_state::No_State_Change) { ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception)); etl::ifsm_state* p_next_state = state_list[next_state_id]; @@ -73,7 +75,7 @@ namespace etl next_state_id = do_enters(p_root, p_next_state, true); - if (next_state_id != ifsm_state::NO_CHANGE) + if (next_state_id != ifsm_state::No_State_Change) { ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception)); p_state = state_list[next_state_id]; @@ -156,17 +158,17 @@ namespace etl } etl::fsm_state_id_t next_state = p_target->on_enter_state(); - ETL_ASSERT(ifsm_state::NO_CHANGE == next_state, ETL_ERROR(etl::fsm_state_enter_state_change_forbidden)); + ETL_ASSERT(ifsm_state::No_State_Change == next_state, ETL_ERROR(etl::fsm_state_composite_state_change_forbidden)); // Activate default child if we need to activate any initial states in an active composite state. if (activate_default_children) { - while (p_target->p_default_active_child != ETL_NULLPTR) + while (p_target->p_default_child != ETL_NULLPTR) { - p_target = p_target->p_default_active_child; + p_target = p_target->p_default_child; p_target->p_parent->p_active_child = p_target; next_state = p_target->on_enter_state(); - ETL_ASSERT(ifsm_state::NO_CHANGE == next_state, ETL_ERROR(etl::fsm_state_enter_state_change_forbidden)); + ETL_ASSERT(ifsm_state::No_State_Change == next_state, ETL_ERROR(etl::fsm_state_composite_state_change_forbidden)); } next_state = p_target->get_state_id(); diff --git a/test/test_fsm.cpp b/test/test_fsm.cpp index cb10c994..d23d9cf7 100644 --- a/test/test_fsm.cpp +++ b/test/test_fsm.cpp @@ -224,7 +224,7 @@ namespace etl::fsm_state_id_t on_event_unknown(const etl::imessage&) { ++get_fsm_context().unknownCount; - return NO_CHANGE; + return No_State_Change; } //*********************************** diff --git a/test/test_hfsm.cpp b/test/test_hfsm.cpp index 1b0ec0f0..6fc9c3ba 100644 --- a/test/test_hfsm.cpp +++ b/test/test_hfsm.cpp @@ -260,14 +260,14 @@ namespace etl::fsm_state_id_t on_event_unknown(const etl::imessage&) { ++get_fsm_context().unknownCount; - return NO_CHANGE; + return No_State_Change; } //*********************************** etl::fsm_state_id_t on_enter_state() { get_fsm_context().TurnRunningLampOff(); - return NO_CHANGE; + return No_State_Change; } }; @@ -290,7 +290,7 @@ namespace etl::fsm_state_id_t on_event_unknown(const etl::imessage&) { ++get_fsm_context().unknownCount; - return NO_CHANGE; + return No_State_Change; } //*********************************** @@ -298,7 +298,7 @@ namespace { get_fsm_context().TurnRunningLampOn(); - return NO_CHANGE; + return No_State_Change; } }; @@ -327,13 +327,13 @@ namespace etl::fsm_state_id_t on_event_unknown(const etl::imessage&) { ++get_fsm_context().unknownCount; - return NO_CHANGE; + return No_State_Change; } etl::fsm_state_id_t on_enter_state() { ++get_fsm_context().windUpStartCount; - return NO_CHANGE; + return No_State_Change; } }; @@ -355,14 +355,14 @@ namespace { ++get_fsm_context().setSpeedCount; get_fsm_context().SetSpeedValue(event.speed); - return NO_CHANGE; + return No_State_Change; } //*********************************** etl::fsm_state_id_t on_event_unknown(const etl::imessage&) { ++get_fsm_context().unknownCount; - return NO_CHANGE; + return No_State_Change; } }; @@ -384,7 +384,7 @@ namespace etl::fsm_state_id_t on_event_unknown(const etl::imessage&) { ++get_fsm_context().unknownCount; - return NO_CHANGE; + return No_State_Change; } }; @@ -400,6 +400,11 @@ namespace &idle, &running, &windingUp, &windingDown, &atSpeed }; + etl::ifsm_state* childStates[] = + { + &windingUp, &atSpeed, &windingDown + }; + MotorControl motorControl; SUITE(test_hfsm_states) @@ -412,9 +417,7 @@ namespace CHECK(motorControl.is_producer()); CHECK(motorControl.is_consumer()); - running.add_initial_child(windingUp); - running.add_child(atSpeed); - running.add_child(windingDown); + running.set_child_states(childStates, etl::size(childStates)); motorControl.Initialise(stateList, etl::size(stateList)); motorControl.reset();