//! \addtogroup StateMachine //! \{ //! \file pistatemachine_state.h //! \brief //! \~english State machine node //! \~russian Узел машины состояний //! \details //! \~english Contains state classes for building state machines //! \~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" //! \~english Base class for state machine states //! \~russian Базовый класс для состояний машины состояний class PIP_EXPORT PIStateBase { friend class PIStateMachine; friend class PITransitionBase; friend class PIStateFinal; public: //! \~english Creates state with name //! \~russian Создает состояние с именем PIStateBase(const PIString & n = {}): name_(n) { ; } virtual ~PIStateBase(); //! \~english Called when state is \~russian Вы entered //! зывается при входе в состояние virtual void onEnter() {} //! \~english Called when state is exited //! \~russian Вызывается при выходе из состояния virtual void onExit() {} //! \~english Called when state machine finishes (for final states) //! \~russian Вызывается при завершении машины состояний (для финальных состояний) virtual void onFinish() {} //! \~english Returns state machine this state belongs to //! \~russian Возвращает машину состояний, которой принадлежит это состояние PIStateMachine * machine() const { return root; } //! \~english Returns parent state //! \~russian Возвращает родительское состояние PIStateBase * parent() const { return parent_state; } //! \~english Returns active child state //! \~russian Возвращает активное дочернее состояние PIStateBase * activeChild() const { return active_state; } //! \~english Returns all active child states //! \~russian Возвращает все активные дочерние состояния PIVector activeChildren() const; //! \~english Returns all active atomic states //! \~russian Возвращает все активные атомарные состояния PIVector activeAtomics() const; //! \~english Adds child state //! \~russian Добавляет дочернее состояние void addState(PIStateBase * s); //! \~english Adds multiple child states //! \~russian Добавляет несколько дочерних состояний void addStates(PIVector s); //! \~english Sets initial state for compound state //! \~russian Устанавливает начальное состояние для составного состояния void setInitialState(PIStateBase * s); //! \~english Adds transition to target state on event //! \~russian Добавляет переход к целевому состоянию по событию PITransitionBase * addTransition(PIStateBase * target, int event_id); //! \~english Adds timeout transition to target state //! \~russian Добавляет переход по таймауту к целевому состоянию PITransitionTimeout * addTimeoutTransition(PIStateBase * target, PISystemTime timeout); //! \~english Sets parallel mode for state //! \~russian Устанавливает параллельный режим для состояния void setParallel(bool yes) { is_parallel = yes; } //! \~english Returns state name //! \~russian Возвращает имя состояния const PIString & getName() const { return name_; } //! \~english Checks if this is root state machine //! \~russian Проверяет является ли это корневой машиной состояний bool isStateMachine() const { return is_root; } //! \~english Checks if state is active //! \~russian Проверяет активно ли состояние bool isActive() const { return is_active; } //! \~english Checks if state is in parallel mode //! \~russian Проверяет находится ли состояние в параллельном режиме bool isParallel() const { return is_parallel; } //! \~english Checks if state is final //! \~russian Проверяет является ли состояние финальным bool isFinal() const { return is_final; } //! \~english Checks if state is atomic (no children) //! \~russian Проверяет является ли состояние атомарным (нет потомков) bool isAtomic() const { return children.isEmpty(); } //! \~english Checks if state is compound (has children) //! \~russian Проверяет является ли состояние составным (есть потомки) bool isCompound() const { return children.isNotEmpty(); } //! \~english Returns child states //! \~russian Возвращает дочерние состояния const PIVector & getChildren() const { return children; } //! \~english Returns transitions from this state //! \~russian Возвращает переходы из этого состояния const PIVector & getTransitions() const { return transitions; } //! \~english Prints state tree to string //! \~russian Выводит дерево состояний в строку void print(PIString prefix = {}); //! \~english Returns all states in machine //! \~russian Возвращает все состояния в машине 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_; }; //! \~english State with lambda callbacks //! \~russian Состояние с lambda коллбэками class PIP_EXPORT PIStateLambda: public PIStateBase { public: //! \~english Creates lambda state with callbacks //! \~russian Создает lambda состояние с коллбэками 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; }; //! \~english Final state of state machine //! \~russian Финальное состояние машины состояний class PIP_EXPORT PIStateFinal: public PIStateBase { public: //! \~english Creates final state with finish callback //! \~russian Создает финальное состояние с коллбэком завершения 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; }; //! \~english Output stream operator for PIStateBase //! \~russian Оператор вывода потока для PIStateBase //! \param c Output stream //! \param s State to output //! \return Reference to output stream inline PICout operator<<(PICout c, PIStateBase * s) { if (!s) c << "state(nullptr)"; else c << ("state(\"" + s->getName() + "\")"); return c; } #endif