mirror of https://github.com/PentHertz/srsLTE.git
enter/exit are now inside the state class. No need for friend classes anymore
This commit is contained in:
parent
2641c6ef08
commit
3ef8c67d67
|
@ -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 f->derived();
|
return static_cast<typename FSM::derived_view*>(f);
|
||||||
}
|
}
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue