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
|
#define SRSLTE_FSM_H
|
||||||
|
|
||||||
#include "choice_type.h"
|
#include "choice_type.h"
|
||||||
|
#include "srslte/common/logmap.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -101,7 +102,7 @@ struct fsm_helper {
|
||||||
{
|
{
|
||||||
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) {
|
if (p != nullptr) {
|
||||||
srslte::get<PrevState>(f->states).exit();
|
srslte::get<PrevState>(f->states).do_exit();
|
||||||
}
|
}
|
||||||
f->states.transit(std::move(*s));
|
f->states.transit(std::move(*s));
|
||||||
srslte::get<State>(f->states).do_enter();
|
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");
|
static_assert(FSM::is_nested, "State is not present in the FSM list of valid states");
|
||||||
if (p != nullptr) {
|
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));
|
handle_state_change(f->parent_fsm()->derived(), s, static_cast<typename FSM::derived_t*>(f));
|
||||||
}
|
}
|
||||||
|
@ -282,6 +283,79 @@ protected:
|
||||||
ParentFSM* fsm_ptr = nullptr;
|
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
|
} // namespace srslte
|
||||||
|
|
||||||
#endif // SRSLTE_FSM_H
|
#endif // SRSLTE_FSM_H
|
||||||
|
|
|
@ -188,9 +188,72 @@ int test_hsm()
|
||||||
return SRSLTE_SUCCESS;
|
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;
|
return SRSLTE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue