mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-30 22:38:44 +08:00
Merge remote-tracking branch 'origin/development'
# Conflicts: # include/etl/version.h
This commit is contained in:
commit
2ce91a95ec
@ -238,21 +238,30 @@ namespace etl
|
||||
/// Starts the FSM.
|
||||
/// Can only be called once.
|
||||
/// Subsequent calls will do nothing.
|
||||
///\param call_on_enter_state If true will call on_enter_state() for the first state. Default = true.
|
||||
///\param call_on_enter_state If will call on_enter_state() for the first state. Default = true.
|
||||
//*******************************************
|
||||
void start(bool call_on_enter_state = true)
|
||||
{
|
||||
// Can only be started once.
|
||||
if (p_state == nullptr)
|
||||
{
|
||||
p_state = state_list[0];
|
||||
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
// Can only be started once.
|
||||
if (p_state == nullptr)
|
||||
{
|
||||
p_state = state_list[0];
|
||||
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
|
||||
if (call_on_enter_state)
|
||||
{
|
||||
p_state->on_enter_state();
|
||||
}
|
||||
}
|
||||
if (call_on_enter_state)
|
||||
{
|
||||
etl::fsm_state_id_t next_state_id;
|
||||
etl::ifsm_state* p_last_state;
|
||||
|
||||
do
|
||||
{
|
||||
p_last_state = p_state;
|
||||
next_state_id = p_state->on_enter_state();
|
||||
p_state = state_list[next_state_id];
|
||||
|
||||
} while (p_last_state != p_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
@ -260,7 +269,7 @@ namespace etl
|
||||
//*******************************************
|
||||
void receive(const etl::imessage& message)
|
||||
{
|
||||
etl::null_message_router nmr;
|
||||
static etl::null_message_router nmr;
|
||||
receive(nmr, message);
|
||||
}
|
||||
|
||||
@ -269,26 +278,26 @@ namespace etl
|
||||
//*******************************************
|
||||
void receive(etl::imessage_router& source, const etl::imessage& message)
|
||||
{
|
||||
etl::fsm_state_id_t next_state_id = p_state->process_event(source, message);
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
etl::fsm_state_id_t next_state_id = p_state->process_event(source, message);
|
||||
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];
|
||||
etl::ifsm_state* p_next_state = state_list[next_state_id];
|
||||
|
||||
// Have we changed state?
|
||||
if (p_next_state != p_state)
|
||||
{
|
||||
do
|
||||
// Have we changed state?
|
||||
if (p_next_state != p_state)
|
||||
{
|
||||
p_state->on_exit_state();
|
||||
p_state = p_next_state;
|
||||
do
|
||||
{
|
||||
p_state->on_exit_state();
|
||||
p_state = p_next_state;
|
||||
|
||||
next_state_id = p_state->on_enter_state();
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
next_state_id = p_state->on_enter_state();
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
|
||||
p_next_state = state_list[next_state_id];
|
||||
p_next_state = state_list[next_state_id];
|
||||
|
||||
} while (p_next_state != p_state); // Have we changed state again?
|
||||
}
|
||||
} while (p_next_state != p_state); // Have we changed state again?
|
||||
}
|
||||
}
|
||||
|
||||
using imessage_router::accepts;
|
||||
|
||||
@ -254,17 +254,26 @@ namespace etl
|
||||
//*******************************************
|
||||
void start(bool call_on_enter_state = true)
|
||||
{
|
||||
// Can only be started once.
|
||||
if (p_state == nullptr)
|
||||
{
|
||||
p_state = state_list[0];
|
||||
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
// Can only be started once.
|
||||
if (p_state == nullptr)
|
||||
{
|
||||
p_state = state_list[0];
|
||||
ETL_ASSERT(p_state != nullptr, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
|
||||
if (call_on_enter_state)
|
||||
{
|
||||
p_state->on_enter_state();
|
||||
}
|
||||
}
|
||||
if (call_on_enter_state)
|
||||
{
|
||||
etl::fsm_state_id_t next_state_id;
|
||||
etl::ifsm_state* p_last_state;
|
||||
|
||||
do
|
||||
{
|
||||
p_last_state = p_state;
|
||||
next_state_id = p_state->on_enter_state();
|
||||
p_state = state_list[next_state_id];
|
||||
|
||||
} while (p_last_state != p_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
@ -272,7 +281,7 @@ namespace etl
|
||||
//*******************************************
|
||||
void receive(const etl::imessage& message)
|
||||
{
|
||||
etl::null_message_router nmr;
|
||||
static etl::null_message_router nmr;
|
||||
receive(nmr, message);
|
||||
}
|
||||
|
||||
@ -281,26 +290,26 @@ namespace etl
|
||||
//*******************************************
|
||||
void receive(etl::imessage_router& source, const etl::imessage& message)
|
||||
{
|
||||
etl::fsm_state_id_t next_state_id = p_state->process_event(source, message);
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
etl::fsm_state_id_t next_state_id = p_state->process_event(source, message);
|
||||
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];
|
||||
etl::ifsm_state* p_next_state = state_list[next_state_id];
|
||||
|
||||
// Have we changed state?
|
||||
if (p_next_state != p_state)
|
||||
{
|
||||
do
|
||||
// Have we changed state?
|
||||
if (p_next_state != p_state)
|
||||
{
|
||||
p_state->on_exit_state();
|
||||
p_state = p_next_state;
|
||||
do
|
||||
{
|
||||
p_state->on_exit_state();
|
||||
p_state = p_next_state;
|
||||
|
||||
next_state_id = p_state->on_enter_state();
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
next_state_id = p_state->on_enter_state();
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
|
||||
p_next_state = state_list[next_state_id];
|
||||
p_next_state = state_list[next_state_id];
|
||||
|
||||
} while (p_next_state != p_state); // Have we changed state again?
|
||||
}
|
||||
} while (p_next_state != p_state); // Have we changed state again?
|
||||
}
|
||||
}
|
||||
|
||||
using imessage_router::accepts;
|
||||
|
||||
@ -76,12 +76,10 @@ namespace etl
|
||||
const etl::message_id_t message_id;
|
||||
|
||||
#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)
|
||||
public:
|
||||
virtual ~imessage()
|
||||
{
|
||||
}
|
||||
#else
|
||||
protected:
|
||||
~imessage()
|
||||
{
|
||||
}
|
||||
|
||||
@ -37,10 +37,10 @@ SOFTWARE.
|
||||
/// Definitions of the ETL version
|
||||
///\ingroup utilities
|
||||
|
||||
#define ETL_VERSION "11.11.1"
|
||||
#define ETL_VERSION "11.11.2"
|
||||
#define ETL_VERSION_MAJOR 11
|
||||
#define ETL_VERSION_MINOR 11
|
||||
#define ETL_VERSION_PATCH 1
|
||||
#define ETL_VERSION_PATCH 2
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -31,9 +31,12 @@ SOFTWARE.
|
||||
#include "fsm.h"
|
||||
#include "enum_type.h"
|
||||
#include "container.h"
|
||||
#include "packet.h"
|
||||
#include "queue.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
const etl::message_router_id_t MOTOR_CONTROL = 0;
|
||||
@ -49,6 +52,7 @@ namespace
|
||||
STOP,
|
||||
STOPPED,
|
||||
SET_SPEED,
|
||||
RECURSIVE,
|
||||
UNSUPPORTED
|
||||
};
|
||||
|
||||
@ -57,6 +61,7 @@ namespace
|
||||
ETL_ENUM_TYPE(STOP, "Stop")
|
||||
ETL_ENUM_TYPE(STOPPED, "Stopped")
|
||||
ETL_ENUM_TYPE(SET_SPEED, "Set Speed")
|
||||
ETL_ENUM_TYPE(RECURSIVE, "Recursive")
|
||||
ETL_ENUM_TYPE(UNSUPPORTED, "Unsupported")
|
||||
ETL_END_ENUM_TYPE
|
||||
};
|
||||
@ -92,6 +97,11 @@ namespace
|
||||
{
|
||||
};
|
||||
|
||||
//***********************************
|
||||
class Recursive : public etl::message<EventId::RECURSIVE>
|
||||
{
|
||||
};
|
||||
|
||||
//***********************************
|
||||
class Unsupported : public etl::message<EventId::UNSUPPORTED>
|
||||
{
|
||||
@ -145,7 +155,7 @@ namespace
|
||||
}
|
||||
|
||||
//***********************************
|
||||
void SetSpeed(int speed_)
|
||||
void SetSpeedValue(int speed_)
|
||||
{
|
||||
speed = speed_;
|
||||
}
|
||||
@ -162,6 +172,19 @@ namespace
|
||||
isLampOn = false;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
template <typename T>
|
||||
void queue_recursive_message(const T& message)
|
||||
{
|
||||
messageQueue.emplace(message);
|
||||
}
|
||||
|
||||
typedef etl::largest<Start, Stop, SetSpeed, Stopped, Recursive> Largest_t;
|
||||
|
||||
typedef etl::packet<etl::imessage, Largest_t::size, Largest_t::alignment> Packet_t;
|
||||
|
||||
etl::queue<Packet_t, 2> messageQueue;
|
||||
|
||||
int startCount;
|
||||
int stopCount;
|
||||
int setSpeedCount;
|
||||
@ -174,7 +197,7 @@ namespace
|
||||
//***********************************
|
||||
// The idle state.
|
||||
//***********************************
|
||||
class Idle : public etl::fsm_state<MotorControl, Idle, StateId::IDLE, Start>
|
||||
class Idle : public etl::fsm_state<MotorControl, Idle, StateId::IDLE, Start, Recursive>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -185,6 +208,13 @@ namespace
|
||||
return StateId::RUNNING;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
etl::fsm_state_id_t on_event(etl::imessage_router&, const Recursive&)
|
||||
{
|
||||
get_fsm_context().queue_recursive_message(Start());
|
||||
return StateId::IDLE;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
etl::fsm_state_id_t on_event_unknown(etl::imessage_router&, const etl::imessage&)
|
||||
{
|
||||
@ -226,7 +256,7 @@ namespace
|
||||
etl::fsm_state_id_t on_event(etl::imessage_router&, const SetSpeed& event)
|
||||
{
|
||||
++get_fsm_context().setSpeedCount;
|
||||
get_fsm_context().SetSpeed(event.speed);
|
||||
get_fsm_context().SetSpeedValue(event.speed);
|
||||
return STATE_ID;
|
||||
}
|
||||
|
||||
@ -309,7 +339,7 @@ namespace
|
||||
CHECK(!motorControl.is_started());
|
||||
|
||||
// Start the FSM.
|
||||
motorControl.start();
|
||||
motorControl.start(false);
|
||||
CHECK(motorControl.is_started());
|
||||
|
||||
// Now in Idle state.
|
||||
@ -447,7 +477,7 @@ namespace
|
||||
CHECK(!motorControl.is_started());
|
||||
|
||||
// Start the FSM.
|
||||
motorControl.start();
|
||||
motorControl.start(false);
|
||||
CHECK(motorControl.is_started());
|
||||
|
||||
// Now in Idle state.
|
||||
@ -484,6 +514,43 @@ namespace
|
||||
CHECK_EQUAL(0, motorControl.unknownCount);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_fsm_recursive_event)
|
||||
{
|
||||
etl::null_message_router nmr;
|
||||
|
||||
motorControl.reset();
|
||||
motorControl.ClearStatistics();
|
||||
|
||||
motorControl.messageQueue.clear();
|
||||
|
||||
// Start the FSM.
|
||||
motorControl.start(false);
|
||||
|
||||
// Now in Idle state.
|
||||
// Send Start event.
|
||||
motorControl.receive(nmr, Recursive());
|
||||
|
||||
CHECK_EQUAL(1, motorControl.messageQueue.size());
|
||||
|
||||
// Send the queued message.
|
||||
motorControl.receive(nmr, motorControl.messageQueue.front().get());
|
||||
motorControl.messageQueue.pop();
|
||||
|
||||
// Now in Running state.
|
||||
|
||||
CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id()));
|
||||
CHECK_EQUAL(StateId::RUNNING, 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(0, motorControl.stopCount);
|
||||
CHECK_EQUAL(0, motorControl.stoppedCount);
|
||||
CHECK_EQUAL(0, motorControl.unknownCount);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_fsm_supported)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user