221 lines
8.5 KiB
C++
221 lines
8.5 KiB
C++
/*! \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 <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#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<PIStateBase *> activeChildren() const;
|
||
|
||
//! \~english Returns all active atomic states
|
||
//! \~russian Возвращает все активные атомарные состояния
|
||
PIVector<PIStateBase *> activeAtomics() const;
|
||
|
||
//! \~english Adds child state
|
||
//! \~russian Добавляет дочернее состояние
|
||
void addState(PIStateBase * s);
|
||
|
||
//! \~english Adds multiple child states
|
||
//! \~russian Добавляет несколько дочерних состояний
|
||
void addStates(PIVector<PIStateBase *> 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<PIStateBase *> & getChildren() const { return children; }
|
||
|
||
//! \~english Returns transitions from this state
|
||
//! \~russian Возвращает переходы из этого состояния
|
||
const PIVector<PITransitionBase *> & getTransitions() const { return transitions; }
|
||
|
||
//! \~english Prints state tree to string
|
||
//! \~russian Выводит дерево состояний в строку
|
||
void print(PIString prefix = {});
|
||
|
||
//! \~english Returns all states in machine
|
||
//! \~russian Возвращает все состояния в машине
|
||
PIVector<PIStateBase *> 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<PIStateBase *> & output);
|
||
void gatherActiveAtomicStates(PIVector<PIStateBase *> & output) const;
|
||
void gatherPathToMachine(PIVector<PIStateBase *> & output);
|
||
PIVector<PIStateBase *> pathToMachine();
|
||
|
||
bool is_active = false, is_root = false, is_parallel = false, is_final = false;
|
||
PIVector<PIStateBase *> children;
|
||
PIVector<PITransitionBase *> 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<void()> on_enter, std::function<void()> 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<void()> 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<void()> on_finish = nullptr, const PIString & n = {}): PIStateBase(n) {
|
||
is_final = true;
|
||
enter = on_finish;
|
||
}
|
||
void onEnter() override {
|
||
if (enter) enter();
|
||
}
|
||
|
||
private:
|
||
std::function<void()> enter;
|
||
};
|
||
|
||
|
||
inline PICout operator<<(PICout c, PIStateBase * s) {
|
||
if (!s)
|
||
c << "state(nullptr)";
|
||
else
|
||
c << ("state(\"" + s->getName() + "\")");
|
||
return c;
|
||
}
|
||
|
||
|
||
#endif
|