diff --git a/lib/include/srslte/common/stack_procedure.h b/lib/include/srslte/common/stack_procedure.h index ff32644e6..ef56af84b 100644 --- a/lib/include/srslte/common/stack_procedure.h +++ b/lib/include/srslte/common/stack_procedure.h @@ -30,7 +30,7 @@ namespace srslte { -enum class proc_outcome_t { repeat, yield, success, error }; +enum class proc_outcome_t { yield, success, error }; /************************************************************************************** * helper functions for method optional overloading @@ -184,11 +184,12 @@ class proc_future_t public: proc_future_t() = default; explicit proc_future_t(const std::shared_ptr >& p_) : ptr(p_) {} - bool is_error() const { return ptr->is_error(); } - bool is_success() const { return ptr->is_success(); } - bool is_complete() const { return ptr->is_complete(); } + bool is_error() const { return not is_empty() and ptr->is_error(); } + bool is_success() const { return not is_empty() and ptr->is_success(); } + bool is_complete() const { return not is_empty() and ptr->is_complete(); } const ResultType* value() const { return is_success() ? ptr->value() : nullptr; } - bool is_valid() const { return ptr != nullptr; } + bool is_empty() const { return ptr == nullptr; } + void clear() { ptr->clear(); } private: std::shared_ptr > ptr; @@ -210,8 +211,6 @@ using proc_future_state_t = proc_future_t; * executes a procedure "action" based on its current internal state, * and return a proc_outcome_t variable with possible values: * - yield - the procedure performed the action but hasn't completed yet. - * - repeat - the same as yield, but explicitly asking that run() should - * recall step() again (probably the procedure state has changed) * - error - the procedure has finished unsuccessfully * - success - the procedure has completed successfully ************************************************************************************/ @@ -223,9 +222,8 @@ public: //! common proc::run() interface. Returns true if procedure is still running bool run() { - proc_outcome_t outcome = proc_outcome_t::repeat; - while (is_busy() and outcome == proc_outcome_t::repeat) { - outcome = step(); + if (is_busy()) { + proc_outcome_t outcome = step(); handle_outcome(outcome); } return is_busy(); @@ -292,20 +290,21 @@ public: //! method to handle external events. "T" must have the method "T::react(const Event&)" for the trigger to take effect template - void trigger(Event&& e) + bool trigger(Event&& e) { if (is_busy()) { proc_outcome_t outcome = proc_ptr->react(std::forward(e)); handle_outcome(outcome); - if (outcome == proc_outcome_t::repeat) { - run(); - } } + return is_busy(); } //! returns an object which the user can use to check if the procedure has ended. proc_future_type get_future() { + if (is_idle()) { + return proc_future_type{}; + } if (future_result == nullptr) { future_result = std::make_shared(); } @@ -326,16 +325,22 @@ public: proc_state = proc_base_t::proc_status_t::on_going; proc_outcome_t init_ret = proc_ptr->init(std::forward(args)...); handle_outcome(init_ret); - switch (init_ret) { - case proc_outcome_t::error: - return false; - case proc_outcome_t::repeat: - run(); // call run right away - break; - default: - break; + return init_ret != proc_outcome_t::error; + } + + //! launch a procedure, returning a future where the result is going to be saved + template + bool launch(proc_future_type* fut, Args&&... args) + { + if (is_busy()) { + fut->clear(); + return fut; } - return true; + proc_state = proc_base_t::proc_status_t::on_going; + *fut = get_future(); + proc_outcome_t init_ret = proc_ptr->init(std::forward(args)...); + handle_outcome(init_ret); + return init_ret != proc_outcome_t::error; } protected: diff --git a/lib/test/common/stack_procedure_test.cc b/lib/test/common/stack_procedure_test.cc index 0a5abeb18..a01fbd464 100644 --- a/lib/test/common/stack_procedure_test.cc +++ b/lib/test/common/stack_procedure_test.cc @@ -216,7 +216,7 @@ static_assert(std::is_same::re int test_local_1() { /* - * Description: Test if a procedure is cleaned automatically after is lifetime has ended + * Description: Test if a procedure is cleaned automatically after its lifetime has ended */ new_test(); printf("\n--- Test %s ---\n", __func__); @@ -297,8 +297,9 @@ int test_callback_2() srslte::proc_t proc; TESTASSERT(not proc.is_busy()); srslte::proc_future_t fut = proc.get_future(); + TESTASSERT(fut.is_empty()); - TESTASSERT(proc.launch(3)); + TESTASSERT(proc.launch(&fut, 3)); TESTASSERT(proc.is_busy()); callbacks.add_proc(std::move(proc)); TESTASSERT(callbacks.size() == 1); @@ -391,8 +392,8 @@ int test_complete_callback_1() TESTASSERT(proc.then_always(continuation_task) == 0) } - srslte::proc_future_t fut = proc.get_future(); - TESTASSERT(proc.launch()); + srslte::proc_future_t fut; + TESTASSERT(proc.launch(&fut)); TESTASSERT(proc.get()->exit_val == "init") while (proc.run()) { TESTASSERT(proc.get()->exit_val == "init") diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index f72545a9c..47f741461 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -91,14 +91,13 @@ proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_interface_rrc_ } Info("Cell has no SIB1. Obtaining SIB1...\n"); - si_acquire_fut = rrc_ptr->si_acquirer.get_future(); - if (not rrc_ptr->si_acquirer.launch(0)) { + if (not rrc_ptr->si_acquirer.launch(&si_acquire_fut, 0)) { // disallow concurrent si_acquire Error("SI Acquire is already running...\n"); return proc_outcome_t::error; } state = state_t::si_acquire; - return proc_outcome_t::repeat; + return step(); } proc_outcome_t rrc::cell_search_proc::react(const cell_search_event_t& event) @@ -178,7 +177,7 @@ proc_outcome_t rrc::si_acquire_proc::init(uint32_t sib_index_) } } - return proc_outcome_t::repeat; + return step(); } proc_outcome_t rrc::si_acquire_proc::step() @@ -261,7 +260,7 @@ proc_outcome_t rrc::serving_cell_config_proc::init(const std::vector& req_idx = 0; search_state = search_state_t::next_sib; - return proc_outcome_t::repeat; + return step(); } proc_outcome_t rrc::serving_cell_config_proc::step() @@ -273,13 +272,12 @@ proc_outcome_t rrc::serving_cell_config_proc::step() if (not rrc_ptr->serving_cell->has_sib(required_sib)) { Info("Cell has no SIB%d. Obtaining SIB%d\n", required_sib + 1, required_sib + 1); - si_acquire_fut = rrc_ptr->si_acquirer.get_future(); - if (not rrc_ptr->si_acquirer.launch(required_sib)) { + if (not rrc_ptr->si_acquirer.launch(&si_acquire_fut, required_sib)) { Error("SI Acquire is already running...\n"); return proc_outcome_t::error; } search_state = search_state_t::si_acquire; - return proc_outcome_t::repeat; + return step(); } else { // UE had SIB already. Handle its SIB Info("Cell has SIB%d\n", required_sib + 1); @@ -313,7 +311,7 @@ proc_outcome_t rrc::serving_cell_config_proc::step() // continue with remaining SIBs search_state = search_state_t::next_sib; req_idx++; - return proc_outcome_t::repeat; + return step(); } return proc_outcome_t::yield; } @@ -342,7 +340,7 @@ proc_outcome_t rrc::cell_selection_proc::init() neigh_index = 0; cs_result = cs_result_t::no_cell; state = search_state_t::cell_selection; - return proc_outcome_t::repeat; + return step(); } proc_outcome_t rrc::cell_selection_proc::step_cell_selection() @@ -366,7 +364,7 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_selection() if (rrc_ptr->phy->cell_select(&rrc_ptr->serving_cell->phy_cell)) { Info("Wait PHY to be in-synch\n"); state = search_state_t::wait_in_sync; - return proc_outcome_t::repeat; + return step(); } else { rrc_ptr->phy_sync_state = phy_unknown_sync; Error("Could not camp on serving cell.\n"); @@ -393,20 +391,18 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_selection() // If can not find any suitable cell, search again Info("Cell selection and reselection in IDLE did not find any suitable cell. Searching again\n"); - cell_search_fut = rrc_ptr->cell_searcher.get_future(); - if (not rrc_ptr->cell_searcher.launch()) { + if (not rrc_ptr->cell_searcher.launch(&cell_search_fut)) { return proc_outcome_t::error; } state = search_state_t::cell_search; - return proc_outcome_t::repeat; + return step(); } proc_outcome_t rrc::cell_selection_proc::step_wait_in_sync() { if (rrc_ptr->phy_sync_state == phy_in_sync) { Info("PHY is in SYNC\n"); - serv_cell_cfg_fut = rrc_ptr->serv_cell_cfg.get_future(); - if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr->ue_required_sibs)) { + if (not rrc_ptr->serv_cell_cfg.launch(&serv_cell_cfg_fut, rrc_ptr->ue_required_sibs)) { return proc_outcome_t::error; } state = search_state_t::cell_config; @@ -444,7 +440,7 @@ proc_outcome_t rrc::cell_selection_proc::step_cell_config() // resume cell selection state = search_state_t::cell_selection; ++neigh_index; - return proc_outcome_t::repeat; + return step(); } proc_outcome_t rrc::cell_selection_proc::step() @@ -480,13 +476,12 @@ rrc::plmn_search_proc::plmn_search_proc(rrc* parent_) : rrc_ptr(parent_), log_h( proc_outcome_t rrc::plmn_search_proc::init() { Info("Starting PLMN search\n"); - nof_plmns = 0; - cell_search_fut = rrc_ptr->cell_searcher.get_future(); - if (not rrc_ptr->cell_searcher.launch()) { + nof_plmns = 0; + if (not rrc_ptr->cell_searcher.launch(&cell_search_fut)) { Error("Failed due to fail to init cell search...\n"); return proc_outcome_t::error; } - return proc_outcome_t::repeat; + return step(); } /* NAS interface to search for available PLMNs. @@ -529,14 +524,13 @@ proc_outcome_t rrc::plmn_search_proc::step() return proc_outcome_t::success; } - cell_search_fut = rrc_ptr->cell_searcher.get_future(); - if (not rrc_ptr->cell_searcher.launch()) { + if (not rrc_ptr->cell_searcher.launch(&cell_search_fut)) { Error("Failed due to fail to init cell search...\n"); return proc_outcome_t::error; } // run again - return proc_outcome_t::repeat; + return step(); } void rrc::plmn_search_proc::then(const srslte::proc_state_t& result) const @@ -624,7 +618,7 @@ proc_outcome_t rrc::connection_request_proc::step() Info("Waiting for RRCConnectionSetup/Reject or expiry\n"); rrc_ptr->dedicated_info_nas = std::move(dedicated_info_nas); state = state_t::wait_t300; - return proc_outcome_t::repeat; + return step(); } else if (state == state_t::wait_t300) { // Wait until t300 stops due to RRCConnectionSetup/Reject or expiry @@ -684,13 +678,12 @@ srslte::proc_outcome_t rrc::connection_request_proc::react(const cell_selection_ // timeAlignmentCommon applied in configure_serving_cell Info("Configuring serving cell...\n"); - serv_cfg_fut = rrc_ptr->serv_cell_cfg.get_future(); - if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr->ue_required_sibs)) { + if (not rrc_ptr->serv_cell_cfg.launch(&serv_cfg_fut, rrc_ptr->ue_required_sibs)) { Error("Attach request failed to configure serving cell...\n"); return proc_outcome_t::error; } state = state_t::config_serving_cell; - return proc_outcome_t::repeat; + return step(); } else { switch (cs_ret) { case cs_result_t::same_cell: @@ -721,7 +714,7 @@ proc_outcome_t rrc::process_pcch_proc::init(const asn1::rrc::paging_s& paging_) paging_idx = 0; state = state_t::next_record; Info("starting...\n"); - return proc_outcome_t::repeat; + return step(); } proc_outcome_t rrc::process_pcch_proc::step() @@ -743,7 +736,7 @@ proc_outcome_t rrc::process_pcch_proc::step() return proc_outcome_t::error; } state = state_t::nas_paging; - return proc_outcome_t::repeat; + return step(); } else { Warning("Received paging while in CONNECT\n"); } @@ -757,8 +750,7 @@ proc_outcome_t rrc::process_pcch_proc::step() rrc_ptr->serving_cell->reset_sibs(); // create a serving cell config procedure and push it to callback list - serv_cfg_fut = rrc_ptr->serv_cell_cfg.get_future(); - if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr->ue_required_sibs)) { + if (not rrc_ptr->serv_cell_cfg.launch(&serv_cfg_fut, rrc_ptr->ue_required_sibs)) { Error("Failed to initiate a serving cell configuration procedure\n"); return proc_outcome_t::error; } @@ -767,7 +759,7 @@ proc_outcome_t rrc::process_pcch_proc::step() return proc_outcome_t::success; } state = state_t::serv_cell_cfg; - return proc_outcome_t::repeat; + return step(); } else if (state == state_t::nas_paging) { // wait for trigger return proc_outcome_t::yield; @@ -799,7 +791,7 @@ proc_outcome_t rrc::process_pcch_proc::react(paging_complete e) paging_idx++; state = state_t::next_record; Info("Received paging complete event\n"); - return proc_outcome_t::repeat; + return step(); } /************************************** @@ -841,8 +833,7 @@ rrc::cell_reselection_proc::cell_reselection_proc(srsue::rrc* rrc_) : rrc_ptr(rr proc_outcome_t rrc::cell_reselection_proc::init() { Info("Starting...\n"); - cell_selection_fut = rrc_ptr->cell_selector.get_future(); - if (not rrc_ptr->cell_selector.launch()) { + if (not rrc_ptr->cell_selector.launch(&cell_selection_fut)) { Error("Failed to initiate a Cell Selection procedure...\n"); return proc_outcome_t::error; } diff --git a/srsue/src/stack/upper/nas.cc b/srsue/src/stack/upper/nas.cc index d516a239d..c6d3f04f1 100644 --- a/srsue/src/stack/upper/nas.cc +++ b/srsue/src/stack/upper/nas.cc @@ -213,7 +213,7 @@ proc_outcome_t nas::rrc_connect_proc::react(nas::rrc_connect_proc::connection_re // Wait until attachment. If doing a service request is already attached state = state_t::wait_attach; // wake up proc - return proc_outcome_t::repeat; + return step(); } else { ProcError("Could not establish RRC connection\n"); return proc_outcome_t::error;