25 #include <initializer_list> 31 #include <boost/optional.hpp> 37 #define DEFINE_STATE_STRUCT(MachineType, ContextType, Id, StructName) \ 38 static constexpr StateId Id = #Id; \ 39 struct StructName : public State<MachineType, ContextType> { \ 40 using State<MachineType, ContextType>::State; \ 41 StateId id() const override { return Id; } \ 42 StateId impl(ContextType& ctx) override; \ 47 using StateId =
const char*;
49 template <
typename MachineType,
typename ContextType>
58 std::map<StateId, uint64_t> transitions_;
61 MachineType* machine_;
64 State(MachineType* ptr) : machine_(ptr) { assert(machine_ !=
nullptr); }
65 virtual ~
State() =
default;
73 virtual StateId
id()
const = 0;
88 virtual StateId
run(ContextType& ctx) {
90 logger()->trace(
"Enter state: {}", this->
id());
92 [&](timer::Milliseconds timing) { this->timing_ms_.
push_back(timing.count()); });
94 StateId next =
impl(ctx);
95 if (next !=
nullptr) {
104 virtual cloe::Logger
logger()
const {
return cloe::logger::get(
"cloe"); }
110 {
"transitions", s.transitions_},
111 {
"timing_ms", s.timing_ms_},
119 virtual StateId
impl(ContextType& ctx) = 0;
122 template <
typename StateType,
typename ContextType>
124 using StateMap = std::map<StateId, std::shared_ptr<StateType>>;
126 StateId prev_state_{
nullptr};
127 StateId interrupt_{
nullptr};
128 std::mutex interrupt_mtx_;
137 const StateMap&
states()
const {
return states_; }
147 template <
typename StateImpl = StateType>
149 return std::dynamic_pointer_cast<StateImpl>(states_.at(
id));
152 StateId run_state(StateId
id, ContextType& ctx) {
153 assert(states_.count(
id) == 1);
154 auto s = states_.at(
id);
156 auto next_id = s->run(ctx);
165 void register_state(StateType* s) {
166 assert(s !=
nullptr);
167 register_state(std::shared_ptr<StateType>(s));
170 void register_state(std::shared_ptr<StateType> s) {
172 assert(states_.count(
id) == 0);
173 states_[
id] = std::move(s);
176 void register_states(std::initializer_list<StateType*> init) {
177 for (
auto& s : init) {
189 logger()->trace(
"Push interrupt: {}",
id);
190 std::lock_guard<std::mutex> guard(interrupt_mtx_);
191 if (interrupt_ !=
nullptr) {
192 throw std::logic_error{
"interrupt queuing is currently not available, already processing: " +
193 std::string(interrupt_)};
198 boost::optional<StateId> pop_interrupt() {
199 std::lock_guard<std::mutex> guard(interrupt_mtx_);
200 if (interrupt_ ==
nullptr) {
203 auto tmp = interrupt_;
204 interrupt_ =
nullptr;
215 virtual StateId handle_interrupt(StateId nominal, StateId interrupt, ContextType& ctx) = 0;
220 virtual cloe::Logger
logger()
const {
return cloe::logger::get(
"cloe"); }
virtual StateId run(ContextType &ctx)
Definition: state_machine.hpp:88
virtual StateId impl(ContextType &ctx)=0
virtual StateId id() const =0
const StateMap & states() const
Definition: state_machine.hpp:137
std::shared_ptr< StateImpl > get_state(StateId id)
Definition: state_machine.hpp:148
void push_back(double x)
Definition: statistics.hpp:134
Definition: state_machine.hpp:123
Definition: state_machine.hpp:50
MachineType * state_machine() const
Definition: state_machine.hpp:81
void push_interrupt(StateId id)
Definition: state_machine.hpp:188
virtual cloe::Logger logger() const
Definition: state_machine.hpp:104
Definition: statistics.hpp:112
Definition: coordinator.cpp:39
StateId previous_state() const
Definition: state_machine.hpp:142