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> template <typename FSM>
using fsm_transitions = typename FSM::derived_view::transitions; using fsm_transitions = typename FSM::derived_view::transitions;
template <typename FSM, typename T> template <typename T>
using state_enter_t = decltype(std::declval<typename FSM::derived_view>().enter(std::declval<T&>())); using enter_op_t = decltype(std::declval<T>().enter(nullptr));
template <typename FSM, typename T> template <typename T>
using state_exit_t = decltype(std::declval<typename FSM::derived_view>().exit(std::declval<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,...) //! Find State in FSM recursively (e.g. find State in FSM,FSM::parentFSM,FSM::parentFSM::parentFSM,...)
template <typename State, typename FSM> 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>(); return &f->states.template get_unchecked<State>();
} }
struct derived_access { template <typename FSM>
template <typename T> typename FSM::derived_view* get_derived(FSM* f)
static typename T::derived_view* get(T* f) {
{ return static_cast<typename FSM::derived_view*>(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 State, typename FSM> template <typename State, typename FSM>
static auto get_state_recursive(FSM* f) -> disable_if_fsm_state<FSM, State, State*> 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"); 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 //! 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"); static_assert(FSM::template can_hold_state<State>(), "FSM type does not hold provided State\n");
using state_t = State; using state_t = State;
using is_subfsm = std::integral_constant<bool, ::srslte::fsm_details::is_subfsm<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_enter = type_utils::is_detected<enter_op_t, State>;
using has_exit = type_utils::is_detected<state_exit_t, FSM, State>; using has_exit = type_utils::is_detected<exit_op_t, State>;
//! enter new state. enter is called recursively for subFSMs //! enter new state. enter is called recursively for subFSMs
static void enter_state(FSM* f, State* s) { enter_(f, s, is_subfsm{}); } static void enter_state(FSM* f, State* s) { enter_(f, s, is_subfsm{}); }
@ -151,9 +144,9 @@ struct state_traits {
template <typename DestState> template <typename DestState>
static disable_if_fsm_state<FSM, DestState> transit_state(FSM* f) 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{}); 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>( parent_state_traits::template transit_state<DestState>(get_derived(f->parent_fsm()));
derived_access::get_parent(f));
} }
private: private:
@ -162,18 +155,18 @@ private:
{ {
using init_type = typename fsm_state_list_type<State>::init_state_t; using init_type = typename fsm_state_list_type<State>::init_state_t;
// set default FSM type // 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 // call FSM enter function
enter_if_exists_(f, s, has_enter{}); enter_if_exists_(f, s, has_enter{});
// call initial substate enter // call initial substate enter
state_traits<typename State::derived_view, init_type>::enter_state( 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 //! 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_(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 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) {} static void exit_if_exists_(FSM* f, State* s, std::false_type) {}
}; };
@ -288,8 +281,6 @@ public:
public: public:
using derived_t = Derived; using derived_t = Derived;
// propagate user fsm methods // propagate user fsm methods
using Derived::enter;
using Derived::exit;
using Derived::states; using Derived::states;
using typename Derived::transitions; using typename Derived::transitions;
}; };
@ -494,16 +485,11 @@ public:
} }
protected: protected:
friend struct fsm_details::derived_access;
// Access to CRTP derived class // Access to CRTP derived class
derived_view* derived() { return static_cast<derived_view*>(this); } derived_view* derived() { return static_cast<derived_view*>(this); }
const derived_view* derived() const { return static_cast<const 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_ref log_h;
srslte::LOG_LEVEL_ENUM fsm_event_log_level = LOG_LEVEL_INFO; srslte::LOG_LEVEL_ENUM fsm_event_log_level = LOG_LEVEL_INFO;
}; };
@ -525,7 +511,6 @@ public:
protected: protected:
using parent_fsm_t = ParentFSM; using parent_fsm_t = ParentFSM;
using fsm_t<Derived>::exit;
ParentFSM* fsm_ptr = nullptr; 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) 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_result_set() const { return value_set; }
bool is_success() const { return value_set and success; } bool is_success() const { return value_set and success; }
const Result& get_result() const { return result; } const Result& get_result() const { return result; }
@ -590,28 +597,6 @@ public:
trigger(proc_launch_ev<Args...>(std::forward<Args>(args)...)); 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: private:
int launch_counter = 0; int launch_counter = 0;
}; };

View File

@ -35,8 +35,13 @@ public:
uint32_t foo_counter = 0; uint32_t foo_counter = 0;
// states // states
struct idle_st {}; struct idle_st {
struct state1 {}; 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_) {} explicit fsm1(srslte::log_ref log_) : srslte::fsm_t<fsm1>(log_) {}
@ -45,8 +50,17 @@ public:
{ {
public: public:
// states // states
struct state_inner {}; struct state_inner {
struct state_inner2 {}; 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_) {} explicit fsm2(fsm1* f_) : nested_fsm_t(f_) {}
~fsm2() { log_h->info("%s being destroyed!", get_type_name(*this).c_str()); } ~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); void inner_action3(state_inner2& s, state1& d, const ev2& e);
protected: 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 // list of states
state_list<state_inner, state_inner2> states{this}; state_list<state_inner, state_inner2> states{this};
using transitions = transition_table<row<state_inner, state_inner, ev1, &fsm2::inner_action1>, 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); void action3(state1& s, idle_st& d, const ev2& e);
protected: protected:
// enter/exit
void enter(idle_st& s);
void enter(state1& s);
void exit(state1& s);
void foo(ev1 e) { foo_counter++; } void foo(ev1 e) { foo_counter++; }
// list of states + transitions // list of states + transitions
@ -93,20 +94,19 @@ protected:
row<state1, idle_st, ev2, &fsm1::action3> >; 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()); f->log_h->info("%s::enter custom called\n", srslte::get_type_name(*this).c_str());
idle_enter_counter++; 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()); f->log_h->info("%s::enter custom called\n", srslte::get_type_name(*this).c_str());
state1_enter_counter++; f->state1_enter_counter++;
} }
void fsm1::state1::exit(fsm1* f)
void fsm1::exit(state1& s)
{ {
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 // 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<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, static_assert(std::is_same<disable_if_fsm_state<fsm1, fsm1::fsm2::state_inner>, void>::value,
"get state list failed\n"); "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 fsm_details
} // namespace srslte } // namespace srslte