enter/exit are now inside the state class. No need for friend classes anymore

This commit is contained in:
Francisco Paisana 2020-05-01 17:46:10 +01:00 committed by Francisco Paisana
parent 2641c6ef08
commit 3ef8c67d67
2 changed files with 68 additions and 82 deletions

View File

@ -97,10 +97,10 @@ using fsm_state_list_type = decltype(std::declval<typename FSM::derived_view>().
template <typename FSM>
using fsm_transitions = typename FSM::derived_view::transitions;
template <typename FSM, typename T>
using state_enter_t = decltype(std::declval<typename FSM::derived_view>().enter(std::declval<T&>()));
template <typename FSM, typename T>
using state_exit_t = decltype(std::declval<typename FSM::derived_view>().exit(std::declval<T&>()));
template <typename T>
using enter_op_t = decltype(std::declval<T>().enter(nullptr));
template <typename T>
using exit_op_t = decltype(std::declval<T>().exit(nullptr));
//! Find State in FSM recursively (e.g. find State in FSM,FSM::parentFSM,FSM::parentFSM::parentFSM,...)
template <typename State, typename FSM>
@ -109,24 +109,17 @@ static auto get_state_recursive(FSM* f) -> enable_if_fsm_state<FSM, State, State
return &f->states.template get_unchecked<State>();
}
struct derived_access {
template <typename T>
static typename T::derived_view* get(T* f)
{
return f->derived();
}
template <typename T>
static typename T::parent_t::derived_view* get_parent(T* f)
{
return f->parent_fsm()->derived();
}
};
template <typename FSM>
typename FSM::derived_view* get_derived(FSM* f)
{
return static_cast<typename FSM::derived_view*>(f);
}
template <typename State, typename FSM>
static auto get_state_recursive(FSM* f) -> disable_if_fsm_state<FSM, State, State*>
{
static_assert(FSM::is_nested, "State is not present in the FSM list of valid states");
return get_state_recursive<State>(derived_access::get_parent(f));
return get_state_recursive<State>(get_derived(f->parent_fsm()));
}
//! Helper type for FSM state-related operations
@ -135,8 +128,8 @@ struct state_traits {
static_assert(FSM::template can_hold_state<State>(), "FSM type does not hold provided State\n");
using state_t = State;
using is_subfsm = std::integral_constant<bool, ::srslte::fsm_details::is_subfsm<State>()>;
using has_enter = type_utils::is_detected<state_enter_t, FSM, State>;
using has_exit = type_utils::is_detected<state_exit_t, FSM, State>;
using has_enter = type_utils::is_detected<enter_op_t, State>;
using has_exit = type_utils::is_detected<exit_op_t, State>;
//! enter new state. enter is called recursively for subFSMs
static void enter_state(FSM* f, State* s) { enter_(f, s, is_subfsm{}); }
@ -151,9 +144,9 @@ struct state_traits {
template <typename DestState>
static disable_if_fsm_state<FSM, DestState> transit_state(FSM* f)
{
using parent_state_traits = state_traits<typename FSM::parent_t::derived_view, typename FSM::derived_t>;
exit_if_exists_(f, &f->states.template get_unchecked<State>(), has_exit{});
state_traits<typename FSM::parent_t::derived_view, typename FSM::derived_t>::template transit_state<DestState>(
derived_access::get_parent(f));
parent_state_traits::template transit_state<DestState>(get_derived(f->parent_fsm()));
}
private:
@ -162,18 +155,18 @@ private:
{
using init_type = typename fsm_state_list_type<State>::init_state_t;
// set default FSM type
derived_access::get(s)->states.template transit<init_type>();
get_derived(s)->states.template transit<init_type>();
// call FSM enter function
enter_if_exists_(f, s, has_enter{});
// call initial substate enter
state_traits<typename State::derived_view, init_type>::enter_state(
derived_access::get(s), &derived_access::get(s)->states.template get_unchecked<init_type>());
get_derived(s), &get_derived(s)->states.template get_unchecked<init_type>());
}
//! In case of State is basic state
static void enter_(FSM* f, State* s, std::false_type) { enter_if_exists_(f, s, has_enter{}); }
static void enter_if_exists_(FSM* f, State* s, std::true_type) { f->enter(*s); }
static void enter_if_exists_(FSM* f, State* s, std::true_type) { s->enter(f); }
static void enter_if_exists_(FSM* f, State* s, std::false_type) {}
static void exit_if_exists_(FSM* f, State* s, std::true_type) { f->exit(*s); }
static void exit_if_exists_(FSM* f, State* s, std::true_type) { s->exit(f); }
static void exit_if_exists_(FSM* f, State* s, std::false_type) {}
};
@ -288,8 +281,6 @@ public:
public:
using derived_t = Derived;
// propagate user fsm methods
using Derived::enter;
using Derived::exit;
using Derived::states;
using typename Derived::transitions;
};
@ -494,16 +485,11 @@ public:
}
protected:
friend struct fsm_details::derived_access;
// Access to CRTP derived class
derived_view* derived() { return static_cast<derived_view*>(this); }
const derived_view* derived() const { return static_cast<const derived_view*>(this); }
void enter() {}
void exit() {}
srslte::log_ref log_h;
srslte::LOG_LEVEL_ENUM fsm_event_log_level = LOG_LEVEL_INFO;
};
@ -525,7 +511,6 @@ public:
protected:
using parent_fsm_t = ParentFSM;
using fsm_t<Derived>::exit;
ParentFSM* fsm_ptr = nullptr;
};
@ -561,6 +546,28 @@ public:
idle_st(bool success_, T&& r) : success(success_), result(std::forward<T>(r)), value_set(true)
{}
void enter(Derived* f)
{
if (f->launch_counter > 0) {
f->log_h->info("FSM \"%s\": Finished run no. %d %s\n",
get_type_name<Derived>().c_str(),
f->launch_counter,
is_success() ? "successfully" : "with an error");
if (not is_result_set()) {
f->log_h->error(
"FSM \"%s\": No result was set for run no. %d\n", get_type_name<Derived>().c_str(), f->launch_counter);
}
}
}
void exit(Derived* f)
{
value_set = false;
success = false;
f->launch_counter++;
f->log_h->info("FSM \"%s\": Starting run no. %d\n", get_type_name<Derived>().c_str(), f->launch_counter);
}
bool is_result_set() const { return value_set; }
bool is_success() const { return value_set and success; }
const Result& get_result() const { return result; }
@ -590,28 +597,6 @@ public:
trigger(proc_launch_ev<Args...>(std::forward<Args>(args)...));
}
protected:
void enter(idle_st& s)
{
if (launch_counter > 0) {
log_h->info("FSM \"%s\": Finished run no. %d %s\n",
get_type_name<Derived>().c_str(),
launch_counter,
s.is_success() ? "successfully" : "with an error");
if (not s.is_result_set()) {
log_h->error(
"FSM \"%s\": No result was set for run no. %d\n", get_type_name<Derived>().c_str(), launch_counter);
}
}
}
void exit(idle_st& s)
{
s = {};
launch_counter++;
log_h->info("FSM \"%s\": Starting run no. %d\n", get_type_name<Derived>().c_str(), launch_counter);
}
private:
int launch_counter = 0;
};

View File

@ -35,8 +35,13 @@ public:
uint32_t foo_counter = 0;
// states
struct idle_st {};
struct state1 {};
struct idle_st {
void enter(fsm1* f);
};
struct state1 {
void enter(fsm1* f);
void exit(fsm1* f);
};
explicit fsm1(srslte::log_ref log_) : srslte::fsm_t<fsm1>(log_) {}
@ -45,8 +50,17 @@ public:
{
public:
// states
struct state_inner {};
struct state_inner2 {};
struct state_inner {
void enter(fsm2* f)
{
f->log_h->info("fsm1::%s::enter called\n", srslte::get_type_name(*this).c_str());
f->parent_fsm()->inner_enter_counter++;
}
};
struct state_inner2 {
void enter(fsm2* f) { f->log_h->info("fsm1::%s::enter called\n", srslte::get_type_name(*this).c_str()); }
void exit(fsm2* f) { f->log_h->info("fsm1::%s::exit called\n", srslte::get_type_name(*this).c_str()); }
};
explicit fsm2(fsm1* f_) : nested_fsm_t(f_) {}
~fsm2() { log_h->info("%s being destroyed!", get_type_name(*this).c_str()); }
@ -57,14 +71,6 @@ public:
void inner_action3(state_inner2& s, state1& d, const ev2& e);
protected:
void enter(state_inner& s)
{
log_h->info("fsm1::%s::enter called\n", srslte::get_type_name(s).c_str());
parent_fsm()->inner_enter_counter++;
}
void enter(state_inner2& s) { log_h->info("fsm1::%s::enter called\n", srslte::get_type_name(s).c_str()); }
void exit(state_inner2& s) { log_h->info("fsm1::%s::exit called\n", srslte::get_type_name(s).c_str()); }
// list of states
state_list<state_inner, state_inner2> states{this};
using transitions = transition_table<row<state_inner, state_inner, ev1, &fsm2::inner_action1>,
@ -78,11 +84,6 @@ private:
void action3(state1& s, idle_st& d, const ev2& e);
protected:
// enter/exit
void enter(idle_st& s);
void enter(state1& s);
void exit(state1& s);
void foo(ev1 e) { foo_counter++; }
// list of states + transitions
@ -93,20 +94,19 @@ protected:
row<state1, idle_st, ev2, &fsm1::action3> >;
};
void fsm1::enter(idle_st& s)
void fsm1::idle_st::enter(fsm1* f)
{
log_h->info("%s::enter custom called\n", srslte::get_type_name(s).c_str());
idle_enter_counter++;
f->log_h->info("%s::enter custom called\n", srslte::get_type_name(*this).c_str());
f->idle_enter_counter++;
}
void fsm1::enter(state1& s)
void fsm1::state1::enter(fsm1* f)
{
log_h->info("%s::enter custom called\n", srslte::get_type_name(s).c_str());
state1_enter_counter++;
f->log_h->info("%s::enter custom called\n", srslte::get_type_name(*this).c_str());
f->state1_enter_counter++;
}
void fsm1::exit(state1& s)
void fsm1::state1::exit(fsm1* f)
{
log_h->info("%s::exit custom called\n", srslte::get_type_name(s).c_str());
f->log_h->info("%s::exit custom called\n", srslte::get_type_name(*this).c_str());
}
// FSM event handlers
@ -157,7 +157,8 @@ static_assert(fsm1::can_hold_state<fsm1::state1>(), "failed can_hold_state check
static_assert(std::is_same<enable_if_fsm_state<fsm1, fsm1::idle_st>, void>::value, "get state list failed\n");
static_assert(std::is_same<disable_if_fsm_state<fsm1, fsm1::fsm2::state_inner>, void>::value,
"get state list failed\n");
static_assert(type_utils::is_detected<state_enter_t, fsm1, fsm1::idle_st>::value, "Failed detection of enter method\n");
static_assert(type_utils::is_detected<enter_op_t, fsm1::idle_st>::value, "Failed detection of enter method\n");
static_assert(not type_utils::is_detected<exit_op_t, fsm1::idle_st>::value, "Failed detection of exit method\n");
} // namespace fsm_details
} // namespace srslte