enter/exit are now being called in order

This commit is contained in:
Francisco Paisana 2020-04-02 18:29:16 +01:00 committed by Francisco Paisana
parent 2e15514d00
commit 1aae510e9d
3 changed files with 49 additions and 14 deletions

View File

@ -401,8 +401,8 @@ bool holds_alternative(const Choice& u)
return u.template is<T>();
}
template <typename T, typename Choice>
T* get_if(Choice& c)
template <typename T, typename... Args>
T* get_if(choice_t<Args...>& c)
{
return c.template get_if<T>();
}

View File

@ -35,8 +35,6 @@ namespace srslte {
// using same_state = mpark::monostate;
struct same_state {
};
template <typename... Args>
using state_list = choice_t<Args...>;
namespace fsm_details {
@ -60,7 +58,7 @@ struct variant_convert {
if (p != nullptr) {
srslte::get<PrevState>(*v).exit();
}
*v = std::move(s);
v->transit(std::move(s));
srslte::get<State>(*v).enter();
}
TargetVariant* v;
@ -76,6 +74,14 @@ struct fsm_helper {
template <typename FSM, typename State>
using disable_if_fsm_state = typename get_fsm_state_list<FSM>::template disable_if_can_hold<State>;
struct enter_visitor {
template <typename State>
void operator()(State&& s)
{
s.do_enter();
}
};
//! Stayed in same state
template <typename FSM, typename PrevState>
static void handle_state_change(FSM* f, same_state* s, PrevState* p)
@ -97,8 +103,8 @@ struct fsm_helper {
if (p != nullptr) {
srslte::get<PrevState>(f->states).exit();
}
f->states = std::move(*s);
srslte::get<State>(f->states).enter();
f->states.transit(std::move(*s));
srslte::get<State>(f->states).do_enter();
}
//! State not present in current FSM. Attempt state transition in parent FSM in the case of NestedFSM
template <typename FSM, typename State, typename PrevState>
@ -164,8 +170,12 @@ class state_t
public:
state_t() = default;
virtual const char* name() const = 0;
virtual void enter() {}
virtual void exit() {}
void do_enter() { enter(); }
void do_exit() { exit(); }
protected:
virtual void enter() {}
virtual void exit() {}
};
//! CRTP Class for all non-nested FSMs
@ -185,6 +195,24 @@ protected:
public:
static const bool is_nested = false;
template <typename... States>
struct state_list : public choice_t<States...> {
using base_t = choice_t<States...>;
template <typename... Args>
state_list(Args&&... args) : base_t(std::forward<Args>(args)...)
{
if (not Derived::is_nested) {
fsm_details::fsm_helper::enter_visitor visitor{};
this->visit(visitor);
}
}
template <typename State>
void transit(State&& s)
{
this->template emplace<State>(std::forward<State>(s));
}
};
// Push Events to FSM
template <typename Ev>
void trigger(Ev&& e)
@ -225,6 +253,13 @@ protected:
// Access to CRTP derived class
derived_view* derived() { return static_cast<derived_view*>(this); }
const derived_view* derived() const { return static_cast<const derived_view*>(this); }
void do_enter()
{
enter();
fsm_details::fsm_helper::enter_visitor visitor{};
derived()->states.visit(visitor);
}
};
template <typename Derived, typename ParentFSM>

View File

@ -79,19 +79,19 @@ public:
auto react(state_inner& s, ev2 e) -> state1;
// list of states
srslte::state_list<state_inner> states;
state_list<state_inner> states;
};
protected:
// transitions
auto react(idle_st& s, ev1 e) -> state1;
auto react(state1& s, ev1 e) -> fsm2;
auto react(state1& s, ev2 e) -> srslte::state_list<idle_st, fsm2>;
auto react(state1& s, ev2 e) -> srslte::choice_t<idle_st, fsm2>;
void foo(ev1 e) { foo_counter++; }
// list of states
srslte::state_list<idle_st, state1, fsm2> states{idle_st{this}};
state_list<idle_st, state1, fsm2> states{idle_st{this}};
};
// FSM event handlers
@ -118,7 +118,7 @@ auto fsm1::react(state1& s, ev1 e) -> fsm2
test_log->info("fsm1::%s::react called\n", s.name());
return fsm2{this};
}
auto fsm1::react(state1& s, ev2 e) -> srslte::state_list<idle_st, fsm2>
auto fsm1::react(state1& s, ev2 e) -> srslte::choice_t<idle_st, fsm2>
{
test_log->info("fsm1::%s::react called\n", s.name());
return idle_st{this};
@ -130,7 +130,7 @@ namespace srslte {
namespace fsm_details {
static_assert(std::is_same<fsm_helper::get_fsm_state_list<fsm1>,
srslte::state_list<fsm1::idle_st, fsm1::state1, fsm1::fsm2> >::value,
fsm1::state_list<fsm1::idle_st, fsm1::state1, fsm1::fsm2> >::value,
"get state list failed\n");
static_assert(std::is_same<fsm_helper::enable_if_fsm_state<fsm1, fsm1::idle_st>, void>::value,
"get state list failed\n");