diff --git a/libs/main/state_machine/pistatemachine_base.h b/libs/main/state_machine/pistatemachine_base.h index e1c8f71f..88f2f561 100644 --- a/libs/main/state_machine/pistatemachine_base.h +++ b/libs/main/state_machine/pistatemachine_base.h @@ -72,7 +72,10 @@ FunctionBase * makeFunction(std::function func) { } // namespace PIStateMachineHelpers class PITransitionBase; +class PITransitionTimeout; class PIStateBase; +class PIStateLambda; +class PIStateFinal; class PIStateMachine; diff --git a/libs/main/state_machine/pistatemachine_state.cpp b/libs/main/state_machine/pistatemachine_state.cpp index 28075ebb..d950425c 100644 --- a/libs/main/state_machine/pistatemachine_state.cpp +++ b/libs/main/state_machine/pistatemachine_state.cpp @@ -23,8 +23,8 @@ PIStateBase::~PIStateBase() { - piDeleteAll(children); piDeleteAll(transitions); + piDeleteAll(children); } @@ -76,9 +76,21 @@ PITransitionBase * PIStateBase::addTransition(PIStateBase * target, int event_id } +PITransitionTimeout * PIStateBase::addTimeoutTransition(PIStateBase * target, PISystemTime timeout) { + PITransitionTimeout * ret = new PITransitionTimeout(this, target, timeout); + ret->root = root; + transitions << ret; + return ret; +} + + void PIStateBase::print(PIString prefix) { - PICout(PICoutManipulators::AddNewLine) << prefix << "[" << (isActive() ? "*" : " ") << "] " << getName() << " active " - << activeChildren(); + auto ac = activeChildren(); + PICout(PICoutManipulators::AddNone) << prefix << "[" << (isActive() ? "*" : " ") << "] \"" << getName() << "\""; + if (ac.isNotEmpty()) + piCout << ", active" << activeChildren(); + else + piCout << ""; prefix += " "; for (auto * c: children) c->print(prefix); @@ -86,6 +98,7 @@ void PIStateBase::print(PIString prefix) { bool PIStateBase::start() { + if (isActive()) return true; if (isAtomic()) { setActive(true); return true; @@ -94,8 +107,10 @@ bool PIStateBase::start() { if (initial_state) { setActive(true); return initial_state->start(); - } else + } else { piCout << "error:" << getName() << "no initial state!"; + return false; + } } else { setActive(true); for (auto * s: children) { @@ -114,12 +129,16 @@ void PIStateBase::setActive(bool yes) { if (parent_state && yes) parent_state->childActived(this); if (!prev_active && is_active) { onEnter(); + for (auto * t: transitions) + t->enabled(); // if (isParallel()) setChildrenActive(true); } if (prev_active && !is_active) { active_state = nullptr; if (isParallel()) setChildrenActiveRecursive(false); onExit(); + for (auto * t: transitions) + t->disabled(); } } diff --git a/libs/main/state_machine/pistatemachine_state.h b/libs/main/state_machine/pistatemachine_state.h index e9749bdb..c01c804d 100644 --- a/libs/main/state_machine/pistatemachine_state.h +++ b/libs/main/state_machine/pistatemachine_state.h @@ -28,6 +28,7 @@ #include "pistatemachine_base.h" #include "pistring.h" +#include "pisystemtime.h" //! \ingroup StateMachine @@ -57,6 +58,7 @@ public: void setInitialState(PIStateBase * s); PITransitionBase * addTransition(PIStateBase * target, int event_id); + PITransitionTimeout * addTimeoutTransition(PIStateBase * target, PISystemTime timeout); void setParallel(bool yes) { is_parallel = yes; } @@ -132,7 +134,7 @@ inline PICout operator<<(PICout c, PIStateBase * s) { if (!s) c << "state(nullptr)"; else - c << ("state(" + s->getName() + ")"); + c << ("state(\"" + s->getName() + "\")"); return c; } diff --git a/libs/main/state_machine/pistatemachine_transition.cpp b/libs/main/state_machine/pistatemachine_transition.cpp index 0b328524..ca95f1f7 100644 --- a/libs/main/state_machine/pistatemachine_transition.cpp +++ b/libs/main/state_machine/pistatemachine_transition.cpp @@ -69,6 +69,7 @@ void PITransitionBase::trigger() { // piCout << "common" << common_count; source_path.remove(source_path.size_s() - common_count, common_count); target_path.remove(target_path.size_s() - common_count, common_count); + // piCout << "source_target_path" << source_target_path; // piCout << "source_path" << source_path; // piCout << "target_path" << target_path; // piCout << "source_state before" << source_state; @@ -92,3 +93,30 @@ void PITransitionBase::trigger() { } if (target_state->isCompound()) target_state->start(); } + + +// PITransitionTimeout + +PITransitionTimeout::PITransitionTimeout(PIStateBase * source, PIStateBase * target, PISystemTime timeout) + : PITransitionBase(source, target, 0) { + timer.setInterval(timeout); + timer.setSlot([this] { + trigger(); + timer.stopLater(); + }); +} + + +PITransitionTimeout::~PITransitionTimeout() { + timer.stop(); +} + + +void PITransitionTimeout::enabled() { + timer.start(); +} + + +void PITransitionTimeout::disabled() { + timer.stopLater(); +} diff --git a/libs/main/state_machine/pistatemachine_transition.h b/libs/main/state_machine/pistatemachine_transition.h index d539fa84..d29d9ae9 100644 --- a/libs/main/state_machine/pistatemachine_transition.h +++ b/libs/main/state_machine/pistatemachine_transition.h @@ -27,6 +27,7 @@ #define pistatemachine_transition_H #include "pistatemachine_base.h" +#include "pitimer.h" //! \ingroup StateMachine @@ -39,7 +40,7 @@ class PIP_EXPORT PITransitionBase { public: PITransitionBase(PIStateBase * source, PIStateBase * target, int event_id); - ~PITransitionBase(); + virtual ~PITransitionBase(); PIStateMachine * machine() const { return root; } PIStateBase * source() const { return source_state; } @@ -74,6 +75,9 @@ public: void trigger(); protected: + virtual void enabled() {} + virtual void disabled() {} + int eventID = 0; PIStateBase *source_state = nullptr, *target_state = nullptr; PIStateMachine * root = nullptr; @@ -81,4 +85,17 @@ protected: std::function action; }; + +class PIP_EXPORT PITransitionTimeout: public PITransitionBase { +public: + PITransitionTimeout(PIStateBase * source, PIStateBase * target, PISystemTime timeout); + ~PITransitionTimeout(); + +private: + void enabled() override; + void disabled() override; + + PITimer timer; +}; + #endif