From 3ef8c67d67877245545524cc4876c3702ae22ad1 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 1 May 2020 17:46:10 +0100 Subject: [PATCH] enter/exit are now inside the state class. No need for friend classes anymore --- lib/include/srslte/common/fsm.h | 95 ++++++++++++++------------------- lib/test/common/fsm_test.cc | 55 +++++++++---------- 2 files changed, 68 insertions(+), 82 deletions(-) diff --git a/lib/include/srslte/common/fsm.h b/lib/include/srslte/common/fsm.h index f3e809eb1..ac3a1befc 100644 --- a/lib/include/srslte/common/fsm.h +++ b/lib/include/srslte/common/fsm.h @@ -97,10 +97,10 @@ using fsm_state_list_type = decltype(std::declval(). template using fsm_transitions = typename FSM::derived_view::transitions; -template -using state_enter_t = decltype(std::declval().enter(std::declval())); -template -using state_exit_t = decltype(std::declval().exit(std::declval())); +template +using enter_op_t = decltype(std::declval().enter(nullptr)); +template +using exit_op_t = decltype(std::declval().exit(nullptr)); //! Find State in FSM recursively (e.g. find State in FSM,FSM::parentFSM,FSM::parentFSM::parentFSM,...) template @@ -109,24 +109,17 @@ static auto get_state_recursive(FSM* f) -> enable_if_fsm_statestates.template get_unchecked(); } -struct derived_access { - template - static typename T::derived_view* get(T* f) - { - return f->derived(); - } - template - static typename T::parent_t::derived_view* get_parent(T* f) - { - return f->parent_fsm()->derived(); - } -}; +template +typename FSM::derived_view* get_derived(FSM* f) +{ + return static_cast(f); +} template static auto get_state_recursive(FSM* f) -> disable_if_fsm_state { static_assert(FSM::is_nested, "State is not present in the FSM list of valid states"); - return get_state_recursive(derived_access::get_parent(f)); + return get_state_recursive(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(), "FSM type does not hold provided State\n"); using state_t = State; using is_subfsm = std::integral_constant()>; - using has_enter = type_utils::is_detected; - using has_exit = type_utils::is_detected; + using has_enter = type_utils::is_detected; + using has_exit = type_utils::is_detected; //! 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 static disable_if_fsm_state transit_state(FSM* f) { + using parent_state_traits = state_traits; exit_if_exists_(f, &f->states.template get_unchecked(), has_exit{}); - state_traits::template transit_state( - derived_access::get_parent(f)); + parent_state_traits::template transit_state(get_derived(f->parent_fsm())); } private: @@ -162,18 +155,18 @@ private: { using init_type = typename fsm_state_list_type::init_state_t; // set default FSM type - derived_access::get(s)->states.template transit(); + get_derived(s)->states.template transit(); // call FSM enter function enter_if_exists_(f, s, has_enter{}); // call initial substate enter state_traits::enter_state( - derived_access::get(s), &derived_access::get(s)->states.template get_unchecked()); + get_derived(s), &get_derived(s)->states.template get_unchecked()); } //! 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(this); } const derived_view* derived() const { return static_cast(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::exit; ParentFSM* fsm_ptr = nullptr; }; @@ -561,6 +546,28 @@ public: idle_st(bool success_, T&& r) : success(success_), result(std::forward(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().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().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().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(std::forward(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().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().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().c_str(), launch_counter); - } - private: int launch_counter = 0; }; diff --git a/lib/test/common/fsm_test.cc b/lib/test/common/fsm_test.cc index 23aef9cc4..1b537b077 100644 --- a/lib/test/common/fsm_test.cc +++ b/lib/test/common/fsm_test.cc @@ -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(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 states{this}; using transitions = transition_table, @@ -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 >; }; -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(), "failed can_hold_state check static_assert(std::is_same, void>::value, "get state list failed\n"); static_assert(std::is_same, void>::value, "get state list failed\n"); -static_assert(type_utils::is_detected::value, "Failed detection of enter method\n"); +static_assert(type_utils::is_detected::value, "Failed detection of enter method\n"); +static_assert(not type_utils::is_detected::value, "Failed detection of exit method\n"); } // namespace fsm_details } // namespace srslte