From 977a1acc5e13376c1291c55959567ffa3e46df35 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 6 Apr 2020 10:41:22 +0100 Subject: [PATCH] eliminated unhandled_event special function. Use react instead. --- lib/include/srslte/common/fsm.h | 71 +++++++++++++++++---------------- lib/test/common/fsm_test.cc | 12 +++++- 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/lib/include/srslte/common/fsm.h b/lib/include/srslte/common/fsm.h index b6d06ff44..6e283a2ed 100644 --- a/lib/include/srslte/common/fsm.h +++ b/lib/include/srslte/common/fsm.h @@ -105,10 +105,15 @@ constexpr bool is_fsm() return std::is_base_of, FSM>::value; } template -constexpr bool is_nested_fsm() +constexpr typename std::enable_if(), bool>::type is_nested_fsm() { return is_fsm() and FSM::is_nested; } +template +constexpr typename std::enable_if(), bool>::type is_nested_fsm() +{ + return false; +} struct fsm_helper { //! Metafunction to determine if FSM can hold given State type @@ -169,42 +174,35 @@ struct fsm_helper { struct trigger_visitor { trigger_visitor(FSM* f_, Event&& ev_) : f(f_), ev(std::forward(ev_)) {} - //! Trigger visitor callback for the current state + /** + * @brief Trigger visitor callback for the current state. + * @description tries to find an fsm::trigger method in case the current state is a nested fsm. If it does not + * find it, searches for a react(current_state&, event) method at the current level + * Stores True in "result" if state changed. False otherwise + */ template void operator()(CurrentState& s) { - call_trigger(&s); + result = call_trigger(&s); + if (not result) { + auto target_state = f->react(s, std::move(ev)); + fsm_helper::handle_state_change(f, &target_state, &s); + result = not std::is_same::value; + } } - //! Check if react exists + //! In case it is a NestedFSM, call the trigger method template - using enable_if_has_react = decltype(std::declval().react(std::declval(), std::declval()), - void()); - - //! In case a "react(State&, Event) -> NextState" method is found - template - auto call_trigger(State* current_state) -> enable_if_has_react + typename std::enable_if(), bool>::type call_trigger(State* s) { - auto target_state = f->react(*current_state, std::move(ev)); - fsm_helper::handle_state_change(f, &target_state, current_state); + return s->trigger(std::move(ev)); } - //! No react method found. Try forward trigger to HSM - template - void call_trigger(State* current_state, Args&&... args) - { - call_trigger_stage2(current_state); - } - //! In case a react(CurrentState&, Event) method is not found, but we are in a NestedFSM with a trigger method - template - auto call_trigger_stage2(State* s) -> decltype(std::declval().trigger(std::declval())) - { - s->trigger(std::move(ev)); - } - //! No trigger or react method found. Do nothing - void call_trigger_stage2(...) { f->unhandled_event(std::move(ev)); } + //! In case a "trigger(Event)" method is not found + bool call_trigger(...) { return false; } FSM* f; Event ev; + bool result = false; }; }; @@ -249,13 +247,12 @@ protected: // propagate fsm_t methods using Derived::base_t::enter; using Derived::base_t::exit; - using Derived::base_t::unhandled_event; + using Derived::base_t::react; // propagate user fsm methods using Derived::enter; using Derived::exit; using Derived::react; using Derived::states; - using Derived::unhandled_event; }; public: @@ -325,10 +322,11 @@ public: // Push Events to FSM template - void trigger(Ev&& e) + bool trigger(Ev&& e) { fsm_details::fsm_helper::trigger_visitor visitor{derived(), std::forward(e)}; srslte::visit(visitor, derived()->states); + return visitor.result; } template @@ -378,11 +376,12 @@ protected: // do nothing by default } - template - void unhandled_event(Event&& e) + template + srslte::same_state react(State& s, Event&& e) { log_fsm_activity( "FSM \"%s\": Unhandled event caught: \"%s\"\n", get_type_name(*this).c_str(), get_type_name().c_str()); + return {}; } template @@ -454,13 +453,15 @@ class proc_fsm_t : public fsm_t protected: using fsm_t::log_h; - using fsm_t::unhandled_event; using fsm_t::enter; using fsm_t::exit; + using fsm_t::react; - void unhandled_event(srslte::proc_launch_ev e) + template + auto react(State&, srslte::proc_launch_ev e) -> srslte::same_state { log_h->warning("Unhandled event \"launch\" caught when procedure is already running\n"); + return {}; } public: @@ -508,8 +509,8 @@ protected: success = false; return {}; } - bool is_success() const { return success; } - Result& get_result() const + bool is_success() const { return success; } + const Result& get_result() const { if (is_success()) { return result; diff --git a/lib/test/common/fsm_test.cc b/lib/test/common/fsm_test.cc index d1cbed688..ae0bde16c 100644 --- a/lib/test/common/fsm_test.cc +++ b/lib/test/common/fsm_test.cc @@ -231,7 +231,12 @@ protected: auto react(complete_st& s, reset_ev ev) -> to_state; // example of uncaught event handling - void unhandled_event(int e) { log_h->info("I dont know how to handle an \"int\" event\n"); } + template + srslte::same_state react(State& s, int e) + { + log_h->info("I dont know how to handle an \"int\" event\n"); + return {}; + } state_list states{this, idle_st{}, procstate1{}, complete_st{}}; }; @@ -244,7 +249,7 @@ auto proc1::react(idle_st& s, srslte::proc_launch_ev ev) -> to_state to_state { log_h->info("success!\n"); - return set_success(); + return set_success(5); } auto proc1::react(procstate1& s, procevent2 ev) -> to_state { @@ -254,6 +259,9 @@ auto proc1::react(procstate1& s, procevent2 ev) -> to_state auto proc1::react(complete_st& s, reset_ev ev) -> to_state { log_h->info("propagate results %s\n", is_success() ? "success" : "failure"); + if (is_success()) { + log_h->info("result was %d\n", get_result()); + } return {}; }