mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
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:
parent
6b3bba3aff
commit
8ac2db0dbe
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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("};")
|
||||
####################################
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user