mirror of https://github.com/PentHertz/srsLTE.git
created a simple procedure fsm
This commit is contained in:
parent
1aae510e9d
commit
ec3ef4474e
|
@ -23,6 +23,7 @@
|
|||
#define SRSLTE_FSM_H
|
||||
|
||||
#include "choice_type.h"
|
||||
#include "srslte/common/logmap.h"
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
@ -101,7 +102,7 @@ struct fsm_helper {
|
|||
{
|
||||
static_assert(not std::is_same<State, PrevState>::value, "State cannot transition to itself.\n");
|
||||
if (p != nullptr) {
|
||||
srslte::get<PrevState>(f->states).exit();
|
||||
srslte::get<PrevState>(f->states).do_exit();
|
||||
}
|
||||
f->states.transit(std::move(*s));
|
||||
srslte::get<State>(f->states).do_enter();
|
||||
|
@ -112,7 +113,7 @@ struct fsm_helper {
|
|||
{
|
||||
static_assert(FSM::is_nested, "State is not present in the FSM list of valid states");
|
||||
if (p != nullptr) {
|
||||
srslte::get<PrevState>(f->states).exit();
|
||||
srslte::get<PrevState>(f->states).do_exit();
|
||||
}
|
||||
handle_state_change(f->parent_fsm()->derived(), s, static_cast<typename FSM::derived_t*>(f));
|
||||
}
|
||||
|
@ -282,6 +283,79 @@ protected:
|
|||
ParentFSM* fsm_ptr = nullptr;
|
||||
};
|
||||
|
||||
template <typename Proc>
|
||||
struct proc_complete_ev {
|
||||
proc_complete_ev(bool success_) : success(success_) {}
|
||||
bool success;
|
||||
};
|
||||
|
||||
// event
|
||||
template <typename... Args>
|
||||
struct proc_launch_ev {
|
||||
std::tuple<Args...> args;
|
||||
explicit proc_launch_ev(Args&&... args_) : args(std::forward<Args>(args_)...) {}
|
||||
};
|
||||
|
||||
template <typename Derived, typename Result = srslte::same_state>
|
||||
class proc_fsm_t : public fsm_t<Derived>
|
||||
{
|
||||
using fsm_type = Derived;
|
||||
using fsm_t<Derived>::derived;
|
||||
|
||||
public:
|
||||
using base_t = proc_fsm_t<Derived, Result>;
|
||||
using fsm_t<Derived>::trigger;
|
||||
|
||||
// states
|
||||
struct idle_st : public state_t {
|
||||
const char* name() const final { return "idle"; }
|
||||
idle_st(Derived* f_) : fsm(f_) {}
|
||||
void exit()
|
||||
{
|
||||
fsm->launch_counter++;
|
||||
fsm->log_h->info("Proc %s: Starting run no. %d\n", fsm->derived()->name(), fsm->launch_counter);
|
||||
}
|
||||
Derived* fsm;
|
||||
};
|
||||
struct complete_st : public srslte::state_t {
|
||||
complete_st(Derived* fsm_, bool success_) : fsm(fsm_), success(success_) {}
|
||||
const char* name() const final { return "complete"; }
|
||||
void enter() { fsm->trigger(srslte::proc_complete_ev<bool>{success}); }
|
||||
Derived* fsm;
|
||||
bool success;
|
||||
};
|
||||
|
||||
explicit proc_fsm_t(srslte::log_ref log_) : log_h(log_) {}
|
||||
|
||||
bool is_running() const { return base_t::template is_in_state<idle_st>(); }
|
||||
|
||||
srslte::log_ref log_h;
|
||||
|
||||
template <typename... Args>
|
||||
void launch(Args&&... args)
|
||||
{
|
||||
trigger(proc_launch_ev<Args...>(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
// template <typename... Args>
|
||||
// void trigger(proc_launch_ev<Args...> e)
|
||||
// {
|
||||
// if (not base_t::template is_in_state<idle_st>()) {
|
||||
// log_h->error("Proc %s: Ignoring launch because procedure is already running\n", base_t::derived()->name());
|
||||
// return;
|
||||
// }
|
||||
// base_t::trigger(std::move(e));
|
||||
// }
|
||||
// template <typename T>
|
||||
// void trigger(T&& t)
|
||||
// {
|
||||
// base_t::trigger(std::forward<T>(t));
|
||||
// }
|
||||
|
||||
private:
|
||||
int launch_counter = 0;
|
||||
};
|
||||
|
||||
} // namespace srslte
|
||||
|
||||
#endif // SRSLTE_FSM_H
|
||||
|
|
|
@ -188,9 +188,72 @@ int test_hsm()
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int main()
|
||||
///////////////////////////
|
||||
|
||||
struct procevent1 {
|
||||
};
|
||||
struct procevent2 {
|
||||
};
|
||||
|
||||
struct proc1 : public srslte::proc_fsm_t<proc1, int> {
|
||||
public:
|
||||
struct procstate1 : public srslte::state_t {
|
||||
const char* name() const final { return "procstate1"; }
|
||||
};
|
||||
|
||||
proc1(srslte::log_ref log_) : base_t(log_) {}
|
||||
|
||||
const char* name() const final { return "proc1"; }
|
||||
|
||||
protected:
|
||||
// Transitions
|
||||
auto react(idle_st& s, srslte::proc_launch_ev<int*> ev) -> procstate1;
|
||||
auto react(procstate1& s, procevent1 ev) -> complete_st;
|
||||
auto react(procstate1& s, procevent2 ev) -> complete_st;
|
||||
auto react(complete_st& s, srslte::proc_complete_ev<bool> ev) -> idle_st;
|
||||
|
||||
state_list<idle_st, procstate1, complete_st> states{this};
|
||||
};
|
||||
|
||||
auto proc1::react(idle_st& s, srslte::proc_launch_ev<int*> ev) -> procstate1
|
||||
{
|
||||
TESTASSERT(test_hsm() == SRSLTE_SUCCESS);
|
||||
log_h->info("started!\n");
|
||||
return {};
|
||||
}
|
||||
auto proc1::react(procstate1& s, procevent1 ev) -> complete_st
|
||||
{
|
||||
log_h->info("success!\n");
|
||||
return {this, true};
|
||||
}
|
||||
auto proc1::react(procstate1& s, procevent2 ev) -> complete_st
|
||||
{
|
||||
log_h->info("failure!\n");
|
||||
return {this, false};
|
||||
}
|
||||
auto proc1::react(complete_st& s, srslte::proc_complete_ev<bool> ev) -> idle_st
|
||||
{
|
||||
log_h->info("propagate results %s\n", s.success ? "success" : "failure");
|
||||
return {this};
|
||||
}
|
||||
|
||||
int test_fsm_proc()
|
||||
{
|
||||
proc1 proc{srslte::logmap::get("TEST")};
|
||||
int v = 2;
|
||||
proc.launch(&v);
|
||||
proc.launch(&v);
|
||||
proc.trigger(procevent1{});
|
||||
proc.launch(&v);
|
||||
proc.trigger(procevent2{});
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
srslte::logmap::get("TEST")->set_level(srslte::LOG_LEVEL_INFO);
|
||||
// TESTASSERT(test_hsm() == SRSLTE_SUCCESS);
|
||||
TESTASSERT(test_fsm_proc() == SRSLTE_SUCCESS);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue