mirror of https://github.com/PentHertz/srsLTE.git
reintroduced optional enter/exit methods for each state
This commit is contained in:
parent
7c76a64238
commit
7dc1489ea7
|
@ -310,11 +310,16 @@ template <typename... Args>
|
||||||
class choice_t : private choice_details::tagged_union_t<Args...>
|
class choice_t : private choice_details::tagged_union_t<Args...>
|
||||||
{
|
{
|
||||||
using base_t = choice_details::tagged_union_t<Args...>;
|
using base_t = choice_details::tagged_union_t<Args...>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! Useful metafunction
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using enable_if_can_hold =
|
using enable_if_can_hold =
|
||||||
typename std::enable_if<base_t::template can_hold_type<typename std::decay<T>::type>()>::type;
|
typename std::enable_if<base_t::template can_hold_type<typename std::decay<T>::type>()>::type;
|
||||||
|
template <typename T>
|
||||||
|
using disable_if_can_hold =
|
||||||
|
typename std::enable_if<not base_t::template can_hold_type<typename std::decay<T>::type>()>::type;
|
||||||
|
|
||||||
public:
|
|
||||||
using base_t::can_hold_type;
|
using base_t::can_hold_type;
|
||||||
using base_t::get;
|
using base_t::get;
|
||||||
using base_t::get_if;
|
using base_t::get_if;
|
||||||
|
@ -408,6 +413,12 @@ const T* get_if(const choice_t<Args...>& c)
|
||||||
return c.template get_if<T>();
|
return c.template get_if<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
T& get(choice_t<Args...>& c)
|
||||||
|
{
|
||||||
|
return c.template get<T>();
|
||||||
|
}
|
||||||
|
|
||||||
template <std::size_t I, typename... Args>
|
template <std::size_t I, typename... Args>
|
||||||
auto get(const choice_t<Args...>& c) -> decltype(c.template get<I>())
|
auto get(const choice_t<Args...>& c) -> decltype(c.template get<I>())
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,13 +57,25 @@ struct variant_convert {
|
||||||
{
|
{
|
||||||
static_assert(not std::is_same<typename std::decay<State>::type, typename std::decay<PrevState>::type>::value,
|
static_assert(not std::is_same<typename std::decay<State>::type, typename std::decay<PrevState>::type>::value,
|
||||||
"State cannot transition to itself.\n");
|
"State cannot transition to itself.\n");
|
||||||
|
if (p != nullptr) {
|
||||||
|
srslte::get<PrevState>(*v).exit();
|
||||||
|
}
|
||||||
*v = std::move(s);
|
*v = std::move(s);
|
||||||
|
srslte::get<State>(*v).enter();
|
||||||
}
|
}
|
||||||
TargetVariant* v;
|
TargetVariant* v;
|
||||||
PrevState* p;
|
PrevState* p;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fsm_helper {
|
struct fsm_helper {
|
||||||
|
//! Metafunction to determine if FSM can hold given State type
|
||||||
|
template <typename FSM>
|
||||||
|
using get_fsm_state_list = decltype(std::declval<typename FSM::derived_view>().states);
|
||||||
|
template <typename FSM, typename State>
|
||||||
|
using enable_if_fsm_state = typename get_fsm_state_list<FSM>::template enable_if_can_hold<State>;
|
||||||
|
template <typename FSM, typename State>
|
||||||
|
using disable_if_fsm_state = typename get_fsm_state_list<FSM>::template disable_if_can_hold<State>;
|
||||||
|
|
||||||
//! Stayed in same state
|
//! Stayed in same state
|
||||||
template <typename FSM, typename PrevState>
|
template <typename FSM, typename PrevState>
|
||||||
static void handle_state_change(FSM* f, same_state* s, PrevState* p)
|
static void handle_state_change(FSM* f, same_state* s, PrevState* p)
|
||||||
|
@ -79,17 +91,25 @@ struct fsm_helper {
|
||||||
}
|
}
|
||||||
//! Simple state transition in FSM
|
//! Simple state transition in FSM
|
||||||
template <typename FSM, typename State, typename PrevState>
|
template <typename FSM, typename State, typename PrevState>
|
||||||
static auto handle_state_change(FSM* f, State* s, PrevState* p) -> decltype(f->states = std::move(*s), void())
|
static enable_if_fsm_state<FSM, State> handle_state_change(FSM* f, State* s, PrevState* p)
|
||||||
{
|
{
|
||||||
static_assert(not std::is_same<State, PrevState>::value, "State cannot transition to itself.\n");
|
static_assert(not std::is_same<State, PrevState>::value, "State cannot transition to itself.\n");
|
||||||
|
if (p != nullptr) {
|
||||||
|
srslte::get<PrevState>(f->states).exit();
|
||||||
|
}
|
||||||
f->states = std::move(*s);
|
f->states = std::move(*s);
|
||||||
|
srslte::get<State>(f->states).enter();
|
||||||
}
|
}
|
||||||
//! State not present in current FSM. Attempt state transition in parent FSM in the case of NestedFSM
|
//! State not present in current FSM. Attempt state transition in parent FSM in the case of NestedFSM
|
||||||
template <typename FSM, typename... Args>
|
template <typename FSM, typename State, typename PrevState>
|
||||||
static void handle_state_change(FSM* f, Args&&... args)
|
static disable_if_fsm_state<FSM, State> handle_state_change(FSM* f, State* s, PrevState* p)
|
||||||
{
|
{
|
||||||
static_assert(FSM::is_nested, "State is not present in the FSM list of valid states");
|
static_assert(FSM::is_nested, "State is not present in the FSM list of valid states");
|
||||||
handle_state_change(f->parent_fsm()->derived(), args...);
|
if (p != nullptr) {
|
||||||
|
srslte::get<PrevState>(f->states).exit();
|
||||||
|
p = nullptr;
|
||||||
|
}
|
||||||
|
handle_state_change(f->parent_fsm()->derived(), s, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Trigger Event, that will result in a state transition
|
//! Trigger Event, that will result in a state transition
|
||||||
|
@ -140,10 +160,12 @@ class state_t
|
||||||
public:
|
public:
|
||||||
state_t() = default;
|
state_t() = default;
|
||||||
virtual const char* name() const = 0;
|
virtual const char* name() const = 0;
|
||||||
|
virtual void enter() {}
|
||||||
|
virtual void exit() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
class fsm_t
|
class fsm_t : public state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// get access to derived protected members from the base
|
// get access to derived protected members from the base
|
||||||
|
@ -155,8 +177,6 @@ public:
|
||||||
};
|
};
|
||||||
static const bool is_nested = false;
|
static const bool is_nested = false;
|
||||||
|
|
||||||
virtual const char* name() const = 0;
|
|
||||||
|
|
||||||
// Push Events to FSM
|
// Push Events to FSM
|
||||||
template <typename Ev>
|
template <typename Ev>
|
||||||
void trigger(Ev&& e)
|
void trigger(Ev&& e)
|
||||||
|
|
|
@ -77,6 +77,10 @@ static_assert(std::is_same<tagged_union_t<char, int, double>::default_type, char
|
||||||
static_assert(tagged_union_t<char, int, double>::can_hold_type<int>(), "Can hold type implementation is incorrect\n");
|
static_assert(tagged_union_t<char, int, double>::can_hold_type<int>(), "Can hold type implementation is incorrect\n");
|
||||||
static_assert(not tagged_union_t<char, int, double>::can_hold_type<uint8_t>(),
|
static_assert(not tagged_union_t<char, int, double>::can_hold_type<uint8_t>(),
|
||||||
"Can hold type implementation is incorrect\n");
|
"Can hold type implementation is incorrect\n");
|
||||||
|
static_assert(std::is_same<choice_t<char, int, double>::enable_if_can_hold<char>, void>::value,
|
||||||
|
"Metafunction enable if not working\n");
|
||||||
|
static_assert(std::is_same<choice_t<char, int, double>::disable_if_can_hold<float>, void>::value,
|
||||||
|
"Metafunction enable if not working\n");
|
||||||
|
|
||||||
} // namespace choice_details
|
} // namespace choice_details
|
||||||
} // namespace srslte
|
} // namespace srslte
|
||||||
|
|
|
@ -38,18 +38,13 @@ public:
|
||||||
uint32_t idle_enter_counter = 0, state1_enter_counter = 0;
|
uint32_t idle_enter_counter = 0, state1_enter_counter = 0;
|
||||||
uint32_t foo_counter = 0;
|
uint32_t foo_counter = 0;
|
||||||
|
|
||||||
fsm1() : states(idle_st{this}) {}
|
|
||||||
|
|
||||||
const char* name() const override { return "fsm1"; }
|
const char* name() const override { return "fsm1"; }
|
||||||
|
|
||||||
// idle state
|
// idle state
|
||||||
struct idle_st : srslte::state_t {
|
struct idle_st : public srslte::state_t {
|
||||||
idle_st(fsm1* f)
|
idle_st(fsm1* f) { f->idle_enter_counter++; }
|
||||||
{
|
void enter() final { test_log->info("fsm1::%s::enter called\n", name()); }
|
||||||
test_log->info("fsm1::%s::enter called\n", name());
|
void exit() final { test_log->info("fsm1::%s::exit called\n", name()); }
|
||||||
f->idle_enter_counter++;
|
|
||||||
}
|
|
||||||
~idle_st() { test_log->info("fsm1::%s::exit called\n", name()); }
|
|
||||||
const char* name() const final { return "idle"; }
|
const char* name() const final { return "idle"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,7 +67,7 @@ public:
|
||||||
struct state_inner : public srslte::state_t {
|
struct state_inner : public srslte::state_t {
|
||||||
const char* name() const final { return "state_inner"; }
|
const char* name() const final { return "state_inner"; }
|
||||||
state_inner() { test_log->info("fsm2::%s::enter called\n", name()); }
|
state_inner() { test_log->info("fsm2::%s::enter called\n", name()); }
|
||||||
~state_inner() { test_log->info("fsm2::%s::exit called\n", name()); }
|
void exit() final { test_log->info("fsm2::%s::exit called\n", name()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
fsm2(fsm1* f_) : nested_fsm_t(f_) { test_log->info("%s::enter called\n", name()); }
|
fsm2(fsm1* f_) : nested_fsm_t(f_) { test_log->info("%s::enter called\n", name()); }
|
||||||
|
@ -130,6 +125,24 @@ auto fsm1::react(state1& s, ev2 e) -> srslte::state_list<idle_st, fsm2>
|
||||||
return idle_st{this};
|
return idle_st{this};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Static Checks
|
||||||
|
|
||||||
|
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,
|
||||||
|
"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");
|
||||||
|
static_assert(std::is_same<fsm_helper::disable_if_fsm_state<fsm1, fsm1::fsm2::state_inner>, void>::value,
|
||||||
|
"get state list failed\n");
|
||||||
|
|
||||||
|
} // namespace fsm_details
|
||||||
|
} // namespace srslte
|
||||||
|
|
||||||
|
// Runtime checks
|
||||||
|
|
||||||
int test_hsm()
|
int test_hsm()
|
||||||
{
|
{
|
||||||
test_log->set_level(srslte::LOG_LEVEL_INFO);
|
test_log->set_level(srslte::LOG_LEVEL_INFO);
|
||||||
|
|
Loading…
Reference in New Issue