Feature/pass partial handled events to parent (#541)

* Pass partial handled events to parent.

* Fix the generator file for C++17.
This commit is contained in:
Jeremy Overesch 2022-04-28 09:29:11 -05:00 committed by GitHub
parent 6b3bba3aff
commit 8ac2db0dbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 21 deletions

View File

@ -179,6 +179,8 @@ namespace etl
// Pass this whenever no state change is desired.
// The highest unsigned value of fsm_state_id_t.
static ETL_CONSTANT fsm_state_id_t No_State_Change = etl::integral_limits<fsm_state_id_t>::max;
// Pass this when this event also needs to be passed to the parent.
static ETL_CONSTANT fsm_state_id_t Pass_To_Parent = No_State_Change - 1U;
/// Allows ifsm_state functions to be private.
friend class etl::fsm;
@ -542,7 +544,7 @@ namespace etl
const bool was_handled = (process_event_type<TMessageTypes>(message, new_state_id) || ...);
if (!was_handled)
if (!was_handled || new_state_id == Pass_To_Parent)
{
new_state_id = (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
}
@ -630,7 +632,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -694,7 +696,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -757,7 +759,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -819,7 +821,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -879,7 +881,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -938,7 +940,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -996,7 +998,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -1053,7 +1055,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -1108,7 +1110,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -1162,7 +1164,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -1215,7 +1217,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -1267,7 +1269,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -1317,7 +1319,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -1366,7 +1368,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -1414,7 +1416,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};
@ -1461,7 +1463,7 @@ namespace etl
default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
}
return new_state_id;
return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
}
};

View File

@ -198,6 +198,8 @@ namespace etl
// Pass this whenever no state change is desired.
// The highest unsigned value of fsm_state_id_t.
static ETL_CONSTANT fsm_state_id_t No_State_Change = etl::integral_limits<fsm_state_id_t>::max;
// Pass this when this event also needs to be passed to the parent.
static ETL_CONSTANT fsm_state_id_t Pass_To_Parent = No_State_Change - 1U;
/// Allows ifsm_state functions to be private.
friend class etl::fsm;
@ -568,7 +570,7 @@ namespace etl
const bool was_handled = (process_event_type<TMessageTypes>(message, new_state_id) || ...);
if (!was_handled)
if (!was_handled || new_state_id == Pass_To_Parent)
{
new_state_id = (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
}
@ -654,7 +656,7 @@ namespace etl
cog.outl(" break;")
cog.outl(" }")
cog.outl("")
cog.outl(" return new_state_id;")
cog.outl(" return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);")
cog.outl(" }")
cog.outl("};")
@ -731,7 +733,7 @@ namespace etl
cog.outl(" break;")
cog.outl(" }")
cog.outl("")
cog.outl(" return new_state_id;")
cog.outl(" return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);")
cog.outl(" }")
cog.outl("};")
####################################

View File

@ -376,10 +376,16 @@ namespace
//***********************************
// The winding down state.
//***********************************
class WindingDown : public etl::fsm_state<MotorControl, WindingDown, StateId::Winding_Down, Stopped>
class WindingDown : public etl::fsm_state<MotorControl, WindingDown, StateId::Winding_Down, Stopped, EStop>
{
public:
etl::fsm_state_id_t on_event(const EStop&)
{
++get_fsm_context().stopCount;
return Pass_To_Parent;
}
//***********************************
etl::fsm_state_id_t on_event(const Stopped&)
{
@ -699,6 +705,61 @@ namespace
CHECK_EQUAL(1, motorControl.windUpStartCount);
}
//*************************************************************************
TEST(test_hfsm_emergency_stop_from_winding_down)
{
etl::null_message_router nmr;
motorControl.Initialise(stateList, std::size(stateList));
motorControl.reset();
motorControl.ClearStatistics();
CHECK(!motorControl.is_started());
// Start the FSM.
motorControl.start(false);
CHECK(motorControl.is_started());
// Now in Idle state.
// Send Start event.
motorControl.receive(Start());
motorControl.receive(Timeout());
motorControl.receive(Stop());
// Now in at speed state.
CHECK_EQUAL(StateId::Winding_Down, int(motorControl.get_state_id()));
CHECK_EQUAL(StateId::Winding_Down, int(motorControl.get_state().get_state_id()));
CHECK_EQUAL(true, motorControl.isLampOn);
CHECK_EQUAL(0, motorControl.setSpeedCount);
CHECK_EQUAL(0, motorControl.speed);
CHECK_EQUAL(1, motorControl.startCount);
CHECK_EQUAL(1, motorControl.stopCount);
CHECK_EQUAL(0, motorControl.stoppedCount);
CHECK_EQUAL(0, motorControl.unknownCount);
CHECK_EQUAL(1, motorControl.windUpCompleteCount);
CHECK_EQUAL(1, motorControl.windUpStartCount);
// Send emergency Stop event.
motorControl.receive(EStop());
// Now in Idle state.
CHECK_EQUAL(StateId::Idle, int(motorControl.get_state_id()));
CHECK_EQUAL(StateId::Idle, int(motorControl.get_state().get_state_id()));
CHECK_EQUAL(false, motorControl.isLampOn);
CHECK_EQUAL(0, motorControl.setSpeedCount);
CHECK_EQUAL(0, motorControl.speed);
CHECK_EQUAL(1, motorControl.startCount);
CHECK_EQUAL(3, motorControl.stopCount);
CHECK_EQUAL(0, motorControl.stoppedCount);
CHECK_EQUAL(0, motorControl.unknownCount);
CHECK_EQUAL(1, motorControl.windUpCompleteCount);
CHECK_EQUAL(1, motorControl.windUpStartCount);
}
//*************************************************************************
TEST(test_hfsm_recursive_event)
{