Program Listing for File base_fsm.hpp
↰ Return to documentation for file (rcppsw/patterns/fsm/base_fsm.hpp
)
#pragma once
/*******************************************************************************
* Includes
******************************************************************************/
#include <cstdio>
#include <cstddef>
#include <string>
#include <memory>
#include <utility>
#include <array>
#include "rcppsw/rcppsw.hpp"
#include "rcppsw/er/client.hpp"
#include "rcppsw/patterns/fsm/event.hpp"
#include "rcppsw/patterns/fsm/state_action.hpp"
#include "rcppsw/patterns/fsm/state_entry_action.hpp"
#include "rcppsw/patterns/fsm/state_exit_action.hpp"
#include "rcppsw/patterns/fsm/state_guard_action.hpp"
#include "rcppsw/patterns/fsm/state_map_ex_row.hpp"
#include "rcppsw/patterns/fsm/state_map_row.hpp"
/*******************************************************************************
* Namespaces/Decls
******************************************************************************/
namespace rcppsw::patterns::fsm {
/*******************************************************************************
* Class Definitions
******************************************************************************/
class base_fsm : public er::client<base_fsm> {
public:
explicit base_fsm(uint8_t max_states, uint8_t initial_state = 0);
~base_fsm(void) override = default;
base_fsm(const base_fsm& other);
base_fsm& operator=(const base_fsm& other);
uint8_t current_state(void) const { return m_current_state; }
uint8_t max_states(void) const { return mc_max_states; }
uint8_t previous_state(void) const { return m_previous_state; }
uint8_t last_state(void) const { return m_last_state; }
void inject_event(int signal, int type);
void inject_event(std::unique_ptr<event_data> event);
virtual void init(void);
protected:
const class event_data* event_data(void) const { return m_event_data.get(); }
class event_data* event_data(void) { return m_event_data.get(); }
std::unique_ptr<class event_data> event_data_release(void) {
return std::move(m_event_data);
}
void generated_event(bool b) { m_event_generated = b; }
bool has_generated_event(void) { return m_event_generated; }
void event_data_hold(bool b) { m_event_data_hold = b; }
bool event_data_hold(void) const { return m_event_data_hold; }
virtual void external_event(uint8_t new_state,
std::unique_ptr<class event_data> data);
void external_event(uint8_t new_state) {
external_event(new_state, nullptr);
}
void internal_event(uint8_t new_state, std::unique_ptr<class event_data> data);
void internal_event(uint8_t new_state) {
internal_event(new_state, std::move(m_event_data));
}
/*
* \brief State machine engine that executes the external event and,
* optionally, all internal events generated during state execution.
*/
void state_engine(void);
uint8_t next_state(void) const { return m_next_state; }
uint8_t initial_state(void) const { return m_initial_state; }
void next_state(uint8_t next_state) { m_next_state = next_state; }
void update_state(uint8_t new_state);
virtual const state_map_row* state_map(RCPPSW_UNUSED size_t) {
return nullptr;
}
virtual const state_map_ex_row* state_map_ex(RCPPSW_UNUSED size_t) {
return nullptr;
}
virtual void state_engine_step(const state_map_row* c_row);
virtual void state_engine_step(const state_map_ex_row* c_row_ex);
private:
void state_engine_map(void);
void state_engine_map_ex(void);
void event_data(std::unique_ptr<class event_data> event_data) {
m_event_data = std::move(event_data);
}
/* clang-format off */
const uint8_t mc_max_states;
uint8_t m_current_state;
uint8_t m_next_state{0};
uint8_t m_initial_state;
uint8_t m_previous_state{0};
uint8_t m_last_state{0};
bool m_event_generated{false};
bool m_event_data_hold{false};
std::unique_ptr<class event_data> m_event_data{nullptr};
/* clang-format on */
};
} /* namespace rcppsw::patterns::fsm */
/*******************************************************************************
* State Macros With Data
******************************************************************************/
#define RCPPSW_FSM_STATE_DECLARE(FSM, state_name, event_data) \
int ST_##state_name(event_data*); \
rcppsw::patterns::fsm:: \
state_action1<FSM, event_data, &FSM::ST_##state_name> \
state_name{}
#define RCPPSW_FSM_STATE_DEFINE(FSM, state_name, event_data) \
int FSM::ST_##state_name(event_data)
#define RCPPSW_FSM_GUARD_DECLARE(FSM, guard_name, event_data) \
bool GD_##guard_name(const event_data*); \
rcppsw::patterns::fsm:: \
state_guard_condition1<FSM, event_data, &FSM::GD_##guard_name> \
guard_name{}
#define RCPPSW_FSM_GUARD_DEFINE(FSM, guard_name, event_data) \
bool FSM::GD_##guard_name(const event_data)
#define RCPPSW_FSM_ENTRY_DECLARE(FSM, entry_name, event_data) \
void EN_##entry_name(const event_data*); \
rcppsw::patterns::fsm:: \
state_entry_action1<FSM, event_data, &FSM::EN_##entry_name> \
entry_name{}
#define RCPPSW_FSM_ENTRY_DEFINE(FSM, entry_name, event_data) \
void FSM::EN_##entry_name(const event_data)
#define RCPPSW_FSM_EXIT_DECLARE(FSM, exit_name) \
void EX_##exit_name(void); \
rcppsw::patterns::fsm::state_exit_action<FSM, &FSM::EX_##exit_name> \
exit_name{}
#define RCPPSW_FSM_EXIT_DEFINE(FSM, exit_name) void FSM::EX_##exit_name(void)
/*******************************************************************************
* State Macros Without Data
******************************************************************************/
#define RCPPSW_FSM_STATE_DECLARE_ND(FSM, state_name, ...) \
int ST_##state_name(void) __VA_ARGS__; \
rcppsw::patterns::fsm::state_action0<FSM, &FSM::ST_##state_name> \
state_name{}
#define RCPPSW_FSM_STATE_DEFINE_ND(FSM, state_name) int FSM::ST_##state_name(void)
#define RCPPSW_FSM_GUARD_DECLARE_ND(FSM, guard_name) \
bool GD_##guard_name(void); \
rcppsw::patterns::fsm::state_guard_condition0<FSM, \
&FSM::GD_##guard_name> \
guard_name{}
#define RCPPSW_FSM_GUARD_DEFINE_ND(FSM, guard_name) bool FSM::GD_##guard_name(void)
#define RCPPSW_FSM_ENTRY_DECLARE_ND(FSM, entry_name) \
void EN_##entry_name(void); \
rcppsw::patterns::fsm::state_entry_action0<FSM, &FSM::EN_##entry_name> \
entry_name{}
#define RCPPSW_FSM_ENTRY_DEFINE_ND(FSM, entry_name) void FSM::EN_##entry_name(void)
/*******************************************************************************
* Transition Map Macros
******************************************************************************/
#define RCPPSW_FSM_DEFINE_TRANSITION_MAP(name) static const uint8_t name[] =
#define RCPPSW_FSM_VERIFY_TRANSITION_MAP(name, n_entries) \
static_assert((sizeof(name) / sizeof(uint8_t)) == (n_entries), \
"Transition map does not cover all states");
/*******************************************************************************
* State Map Macros
******************************************************************************/
#define RCPPSW_FSM_DECLARE_STATE_MAP(type, name, n_entries) \
const std::array<rcppsw::patterns::fsm::RCSW_JOIN(type, _row), \
n_entries> name
#define RCPPSW_FSM_DEFINE_STATE_MAP(name, ...) name {__VA_ARGS__}
#define RCPPSW_FSM_DEFINE_STATE_MAP_ACCESSOR(type, index_var) \
const rcppsw::patterns::fsm::RCSW_JOIN(type, _row) * \
type(size_t index_var)
#define RCPPSW_FSM_STATE_MAP_ENTRY(state_name) \
rcppsw::patterns::fsm::state_map_row(state_name)
#define RCPPSW_FSM_STATE_MAP_ENTRY_EX(state_name) \
rcppsw::patterns::fsm::state_map_ex_row( \
state_name, NULL, NULL, NULL)
#define RCPPSW_FSM_STATE_MAP_ENTRY_EX_ALL( \
state_name, guard_name, entry_name, exit_name) \
rcppsw::patterns::fsm::state_map_ex_row( \
state_name, guard_name, entry_name, exit_name)