/*! \file pistatemachine_state.h * \ingroup StateMachine * \~\brief * \~english State machine node * \~russian Узел машины состояний */ /* PIP - Platform Independent Primitives State machine node Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef pistatemachine_state_H #define pistatemachine_state_H #include "pistatemachine_base.h" #include "pistring.h" #include "pisystemtime.h" //! \ingroup StateMachine //! \~\brief //! \~english //! \~russian class PIP_EXPORT PIStateBase { friend class PIStateMachine; friend class PITransitionBase; friend class PIStateFinal; public: PIStateBase(const PIString & n = {}): name_(n) { ; } virtual ~PIStateBase(); virtual void onEnter() {} virtual void onExit() {} virtual void onFinish() {} PIStateMachine * machine() const { return root; } PIStateBase * parent() const { return parent_state; } PIStateBase * activeChild() const { return active_state; } PIVector activeChildren() const; PIVector activeAtomics() const; void addState(PIStateBase * s); void addStates(PIVector s); void setInitialState(PIStateBase * s); PITransitionBase * addTransition(PIStateBase * target, int event_id); PITransitionTimeout * addTimeoutTransition(PIStateBase * target, PISystemTime timeout); void setParallel(bool yes) { is_parallel = yes; } const PIString & getName() const { return name_; } bool isStateMachine() const { return is_root; } bool isActive() const { return is_active; } bool isParallel() const { return is_parallel; } bool isFinal() const { return is_final; } bool isAtomic() const { return children.isEmpty(); } bool isCompound() const { return children.isNotEmpty(); } const PIVector & getChildren() const { return children; } const PIVector & getTransitions() const { return transitions; } void print(PIString prefix = {}); PIVector gatherStates(); private: bool start(bool force = false); void setActive(bool yes); void setActiveRecursive(bool yes); void setChildrenActive(bool yes); void setChildrenActiveRecursive(bool yes); void activeChild(PIStateBase * c); void childActived(PIStateBase * s); void propagateRoot(PIStateMachine * r); void gatherActiveStates(PIVector & output); void gatherActiveAtomicStates(PIVector & output) const; void gatherPathToMachine(PIVector & output); PIVector pathToMachine(); bool is_active = false, is_root = false, is_parallel = false, is_final = false; PIVector children; PIVector transitions; PIStateBase *active_state = nullptr, *initial_state = nullptr, *parent_state = nullptr; PIStateMachine * root = nullptr; PIString name_; }; class PIP_EXPORT PIStateLambda: public PIStateBase { public: PIStateLambda(std::function on_enter, std::function on_exit = nullptr, const PIString & n = {}): PIStateBase(n) { enter = on_enter; exit = on_exit; } void onEnter() override { if (enter) enter(); } void onExit() override { if (exit) exit(); } private: std::function enter, exit; }; class PIP_EXPORT PIStateFinal: public PIStateBase { public: PIStateFinal(std::function on_finish = nullptr, const PIString & n = {}): PIStateBase(n) { is_final = true; enter = on_finish; } void onEnter() override { if (enter) enter(); } private: std::function enter; }; inline PICout operator<<(PICout c, PIStateBase * s) { if (!s) c << "state(nullptr)"; else c << ("state(\"" + s->getName() + "\")"); return c; } #endif