add ability for fsms to self-trigger

This commit is contained in:
Francisco Paisana 2020-06-10 12:45:54 +01:00
parent 9f98bb3f54
commit 12dda03bb8
2 changed files with 67 additions and 5 deletions

View File

@ -25,6 +25,7 @@
#include "srslte/common/logmap.h"
#include "type_utils.h"
#include <cstdio>
#include <functional>
#include <limits>
#include <memory>
#include <tuple>
@ -418,9 +419,18 @@ public:
template <typename Ev>
bool trigger(Ev&& e)
{
fsm_details::trigger_visitor<derived_view, Ev> visitor{derived(), std::forward<Ev>(e)};
srslte::visit(visitor, derived()->states);
return visitor.result;
if (trigger_locked) {
pending_events.emplace_back([e](fsm_t<Derived>* d) { d->process_event(e); });
return false;
}
trigger_locked = true;
bool ret = process_event(std::forward<Ev>(e));
while (not pending_events.empty()) {
pending_events.front()(this);
pending_events.pop_front();
}
trigger_locked = false;
return ret;
}
template <typename State>
@ -493,8 +503,18 @@ protected:
const derived_view* derived() const { return static_cast<const derived_view*>(this); }
srslte::log_ref log_h;
srslte::LOG_LEVEL_ENUM fsm_event_log_level = LOG_LEVEL_INFO;
template <typename Ev>
bool process_event(Ev&& e)
{
fsm_details::trigger_visitor<derived_view, Ev> visitor{derived(), std::forward<Ev>(e)};
srslte::visit(visitor, derived()->states);
return visitor.result;
}
srslte::log_ref log_h;
srslte::LOG_LEVEL_ENUM fsm_event_log_level = LOG_LEVEL_INFO;
bool trigger_locked = false;
std::deque<std::function<void(fsm_t<Derived>*)> > pending_events;
};
template <typename Derived, typename ParentFSM>

View File

@ -451,6 +451,46 @@ int test_nas_fsm()
return SRSLTE_SUCCESS;
}
struct fsm3 : public srslte::fsm_t<fsm3> {
struct st1 {};
struct st2 {
int counter = 0;
void enter(fsm3* fsm) { counter++; }
};
fsm3() : base_t(srslte::log_ref{"TEST"}) {}
protected:
void handle_ev1(st1& s, st2& d, const ev1& ev) { trigger(ev2{}); }
void handle_ev2(st2& s, st1& d, const ev2& ev)
{
if (s.counter < 2) {
trigger(ev1{});
}
}
state_list<st1, st2> states{this};
// clang-format off
using transitions = transition_table<
// Start Target Event Action
// +------------------------+-------------------------+-------------------+--------------------+
row< st1, st2, ev1, &fsm3::handle_ev1>,
row< st2, st1, ev2, &fsm3::handle_ev2>
>;
// clang-format on
};
int test_fsm_self_trigger()
{
fsm3 fsm;
TESTASSERT(fsm.is_in_state<fsm3::st1>());
fsm.trigger(ev1{});
TESTASSERT(fsm.is_in_state<fsm3::st1>());
return SRSLTE_SUCCESS;
}
int main()
{
srslte::log_ref testlog{"TEST"};
@ -461,6 +501,8 @@ int main()
testlog->info("TEST \"proc\" finished successfully\n\n");
TESTASSERT(test_nas_fsm() == SRSLTE_SUCCESS);
testlog->info("TEST \"nas fsm\" finished successfully\n\n");
TESTASSERT(test_fsm_self_trigger() == SRSLTE_SUCCESS);
testlog->info("TEST \"fsm self trigger\" finished successfully\n\n");
return SRSLTE_SUCCESS;
}