//! \~\file pistatemachine_state.h //! \~\ingroup StateMachine //! \~\brief //! \~english Declares states used by PIStateMachine //! \~russian Объявляет состояния, используемые в PIStateMachine /* PIP - Platform Independent Primitives State machine node Ivan Pelipenko peri4ko@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 Base class for states in a hierarchical state machine. //! \~russian Базовый класс состояния в иерархической машине состояний. //! \~\details //! \~english //! A state can own child states and outgoing transitions. Compound states activate //! either their initial child state or all children when parallel mode is enabled. //! \~russian //! Состояние может владеть дочерними состояниями и исходящими переходами. //! Составные состояния активируют либо начальное дочернее состояние, либо все //! дочерние состояния при включенном параллельном режиме. class PIP_EXPORT PIStateBase { friend class PIStateMachine; friend class PITransitionBase; friend class PIStateFinal; public: //! \~english Creates a state with an optional diagnostic name. //! \~russian Создает состояние с необязательным именем для диагностики. PIStateBase(const PIString & n = {}): name_(n) { ; } //! \~english Destroys the state together with owned child states and transitions. //! \~russian Уничтожает состояние вместе с принадлежащими дочерними состояниями и переходами. virtual ~PIStateBase(); //! \~english Called when the state becomes active. //! \~russian Вызывается при активации состояния. virtual void onEnter() {} //! \~english Called when the state becomes inactive. //! \~russian Вызывается при деактивации состояния. virtual void onExit() {} //! \~english Called when a final child finishes this state. //! \~russian Вызывается, когда финальное дочернее состояние завершает это состояние. virtual void onFinish() {} //! \~english Returns the root state machine. //! \~russian Возвращает корневую машину состояний. PIStateMachine * machine() const { return root; } //! \~english Returns the parent state. //! \~russian Возвращает родительское состояние. PIStateBase * parent() const { return parent_state; } //! \~english Returns the active child of a non-parallel compound state. //! \~russian Возвращает активное дочернее состояние непараллельного составного состояния. PIStateBase * activeChild() const { return active_state; } //! \~english Returns active child states. //! \~russian Возвращает активные дочерние состояния. PIVector activeChildren() const; //! \~english Returns active atomic leaf states below this state. //! \~russian Возвращает активные атомарные листовые состояния под этим состоянием. PIVector activeAtomics() const; //! \~english Adds a child state owned by this state. //! \~russian Добавляет дочернее состояние, которым владеет это состояние. void addState(PIStateBase * s); //! \~english Adds multiple child states owned by this state. //! \~russian Добавляет несколько дочерних состояний, которыми владеет это состояние. void addStates(PIVector s); //! \~english Sets the initial child state for a non-parallel compound state. //! \~russian Задает начальное дочернее состояние для непараллельного составного состояния. void setInitialState(PIStateBase * s); //! \~english Adds an event-driven transition from this state to \a target. //! \~russian Добавляет переход по событию из этого состояния в \a target. PITransitionBase * addTransition(PIStateBase * target, int event_id); //! \~english Adds a timeout transition that fires while this state stays active. //! \~russian Добавляет переход по таймауту, который срабатывает пока это состояние активно. PITransitionTimeout * addTimeoutTransition(PIStateBase * target, PISystemTime timeout); //! \~english Enables or disables parallel activation of child states. //! \~russian Включает или выключает параллельную активацию дочерних состояний. void setParallel(bool yes) { is_parallel = yes; } //! \~english Returns the state name. //! \~russian Возвращает имя состояния. const PIString & getName() const { return name_; } //! \~english Returns true for the root machine object. //! \~russian Возвращает true для корневого объекта машины состояний. bool isStateMachine() const { return is_root; } //! \~english Returns true if the state is currently active. //! \~russian Возвращает true, если состояние сейчас активно. bool isActive() const { return is_active; } //! \~english Returns true if child states are activated in parallel. //! \~russian Возвращает true, если дочерние состояния активируются параллельно. bool isParallel() const { return is_parallel; } //! \~english Returns true if the state is marked as final. //! \~russian Возвращает true, если состояние помечено как финальное. bool isFinal() const { return is_final; } //! \~english Returns true if the state has no children. //! \~russian Возвращает true, если у состояния нет дочерних состояний. bool isAtomic() const { return children.isEmpty(); } //! \~english Returns true if the state owns child states. //! \~russian Возвращает true, если состояние содержит дочерние состояния. bool isCompound() const { return children.isNotEmpty(); } //! \~english Returns direct child states. //! \~russian Возвращает прямые дочерние состояния. const PIVector & getChildren() const { return children; } //! \~english Returns outgoing transitions owned by this state. //! \~russian Возвращает исходящие переходы, принадлежащие этому состоянию. const PIVector & getTransitions() const { return transitions; } //! \~english Prints the state tree and active branches to piCout. //! \~russian Печатает дерево состояний и активные ветви в piCout. void print(PIString prefix = {}); //! \~english Returns this state and all descendant states. //! \~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_; }; //! \~\ingroup StateMachine //! \~\brief //! \~english State implementation that forwards enter and exit virtual methods to callbacks. //! \~russian Реализация состояния, которая перенаправляет виртуальные методы входа и выхода в callback-функции. class PIP_EXPORT PIStateLambda: public PIStateBase { public: //! \~english Creates a state backed by enter and exit callbacks. //! \~russian Создает состояние с callback-функциями входа и выхода. PIStateLambda(std::function on_enter, std::function on_exit = nullptr, const PIString & n = {}): PIStateBase(n) { enter = on_enter; exit = on_exit; } //! \~english Executes the enter callback. //! \~russian Выполняет callback-функцию входа. void onEnter() override { if (enter) enter(); } //! \~english Executes the exit callback. //! \~russian Выполняет callback-функцию выхода. void onExit() override { if (exit) exit(); } private: std::function enter, exit; }; //! \~\ingroup StateMachine //! \~\brief //! \~english Final state that finishes its parent state when entered. //! \~russian Финальное состояние, которое завершает родительское состояние при входе. class PIP_EXPORT PIStateFinal: public PIStateBase { public: //! \~english Creates a final state with an optional callback executed on entry. //! \~russian Создает финальное состояние с необязательной callback-функцией, выполняемой при входе. PIStateFinal(std::function on_finish = nullptr, const PIString & n = {}): PIStateBase(n) { is_final = true; enter = on_finish; } //! \~english Executes the finish callback when the final state is entered. //! \~russian Выполняет callback завершения при входе в финальное состояние. void onEnter() override { if (enter) enter(); } private: std::function enter; }; //! \relatesalso PIStateBase //! \~english Writes a textual representation of a state to PICout. //! \~russian Записывает текстовое представление состояния в PICout. inline PICout operator<<(PICout c, PIStateBase * s) { if (!s) c << "state(nullptr)"; else c << ("state(\"" + s->getName() + "\")"); return c; } #endif