created a simple procedure fsm

This commit is contained in:
Francisco Paisana 2020-04-02 20:30:33 +01:00 committed by Francisco Paisana
parent 1aae510e9d
commit ec3ef4474e
2 changed files with 141 additions and 4 deletions

View File

@ -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

View File

@ -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;
}