Merge branch 'master' into pico_sdk

This commit is contained in:
2026-03-29 12:28:36 +03:00
359 changed files with 56129 additions and 6404 deletions

View File

@@ -1,13 +1,19 @@
/*! \file pistatemachine.h
* \ingroup StateMachine
* \~\brief
* \~english State machine.
* \~russian Машина состояний.
*/
//! \~\file pistatemachine.h
//! \brief
//! \~english State machine.
//! \~russian Машина состояний.
//! \details
//! \~english Main state machine class that manages states and transitions.
//! \~russian Основной класс машины состояний, управляющий состояниями и переходами.
//! \note
//! \~english Thread-safe implementation with nested post handling.
//! \~russian Потокобезопасная реализация с обработкой вложенных постов.
//! \~\sa
//! PIStateBase, PITransitionBase
/*
PIP - Platform Independent Primitives
State machine
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
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
@@ -30,18 +36,32 @@
#include "pistatemachine_transition.h"
//! \ingroup StateMachine
//! \~\ingroup StateMachine
//! \~\brief
//! \~english
//! \~russian
//! \~english Root object that owns and runs a hierarchical state machine.
//! \~russian Корневой объект, который владеет и запускает иерархическую машину состояний.
class PIP_EXPORT PIStateMachine: public PIStateBase {
public:
//! \~english Creates a state machine with an optional name.
//! \~russian Создает машину состояний с необязательным именем.
PIStateMachine(const PIString & n = {});
bool start();
bool isRunning() const { return is_running; }
void setOnFinish(std::function<void()> f) { on_finish = f; }
//! \~english Starts the machine from its initial active configuration.
//! \~russian Запускает машину из ее начальной активной конфигурации.
bool start();
//! \~english Returns true while the machine is running.
//! \~russian Возвращает true, пока машина запущена.
bool isRunning() const { return is_running; }
//! \~english Sets a callback invoked when the machine finishes.
//! \~russian Задает callback-функцию, вызываемую при завершении машины.
void setOnFinish(std::function<void()> f) { on_finish = std::move(f); }
//! \~english Posts an event to active states and triggers the first matching transition.
//! \~russian Посылает событие в активные состояния и запускает первый подходящий переход.
template<typename... Args>
bool postEvent(int event_id, Args... args) {
if (!is_running) return false;
@@ -83,6 +103,7 @@ public:
return false;
}
private:
void onFinish() override;

View File

@@ -1,13 +1,12 @@
/*! \file pistatemachine_base.h
* \ingroup StateMachine
* \~\brief
* \~english Some template helpers for PIStateMachine
* \~russian Несколько шаблонов для PIStateMachine
*/
//! \~\file pistatemachine_base.h
//! \~\ingroup StateMachine
//! \~\brief
//! \~english Declares helper types shared by the state machine API
//! \~russian Объявляет вспомогательные типы, общие для API машины состояний
/*
PIP - Platform Independent Primitives
Some template helpers for PIStateMachine
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
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
@@ -37,6 +36,7 @@ public:
virtual uint formatHash() = 0;
};
template<typename... Args>
class Function: public FunctionBase {
public:
@@ -51,10 +51,11 @@ public:
std::function<bool(Args...)> func;
};
template<typename Ret, typename... Args>
FunctionBase * makeFunction(std::function<Ret(Args...)> func) {
auto * ret = new Function<Args...>();
ret->func = func;
ret->func = std::move(func);
return ret;
}

View File

@@ -1,13 +1,12 @@
/*! \file pistatemachine_state.h
* \ingroup StateMachine
* \~\brief
* \~english State machine node
* \~russian Узел машины состояний
*/
//! \~\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, Andrey Bychkov work.a.b@yandex.ru
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
@@ -31,52 +30,141 @@
#include "pisystemtime.h"
//! \ingroup StateMachine
//! \~\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<PIStateBase *> activeChildren() const;
//! \~english Returns active atomic leaf states below this state.
//! \~russian Возвращает активные атомарные листовые состояния под этим состоянием.
PIVector<PIStateBase *> 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<PIStateBase *> 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<PIStateBase *> & getChildren() const { return children; }
//! \~english Returns outgoing transitions owned by this state.
//! \~russian Возвращает исходящие переходы, принадлежащие этому состоянию.
const PIVector<PITransitionBase *> & 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<PIStateBase *> gatherStates();
private:
bool start(bool force = false);
void setActive(bool yes);
@@ -100,39 +188,66 @@ private:
};
//! \~\ingroup StateMachine
//! \~\brief
//! \~english State implementation that forwards enter and exit virtual methods to callbacks.
//! \~russian Реализация состояния, которая перенаправляет виртуальные методы входа и выхода в callback-функции.
class PIP_EXPORT PIStateLambda: public PIStateBase {
public:
PIStateLambda(std::function<void()> on_enter, std::function<void()> on_exit = nullptr, const PIString & n = {}): PIStateBase(n) {
enter = on_enter;
exit = on_exit;
}
//! \~english Creates a state backed by enter and exit callbacks.
//! \~russian Создает состояние с callback-функциями входа и выхода.
PIStateLambda(std::function<void()> on_enter, std::function<void()> on_exit = nullptr, const PIString & n = {})
: PIStateBase(n)
, enter(std::move(on_enter))
, exit(std::move(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<void()> enter, exit;
};
//! \~\ingroup StateMachine
//! \~\brief
//! \~english Final state that finishes its parent state when entered.
//! \~russian Финальное состояние, которое завершает родительское состояние при входе.
class PIP_EXPORT PIStateFinal: public PIStateBase {
public:
PIStateFinal(std::function<void()> on_finish = nullptr, const PIString & n = {}): PIStateBase(n) {
//! \~english Creates a final state with an optional callback executed on entry.
//! \~russian Создает финальное состояние с необязательной callback-функцией, выполняемой при входе.
PIStateFinal(std::function<void()> on_finish = nullptr, const PIString & n = {}): PIStateBase(n), enter(std::move(on_finish)) {
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<void()> 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)";

View File

@@ -35,7 +35,7 @@ PITransitionBase::~PITransitionBase() {
PITransitionBase * PITransitionBase::addAction(std::function<void()> a) {
action = a;
action = std::move(a);
return this;
}

View File

@@ -1,13 +1,12 @@
/*! \file pistatemachine_transition.h
* \ingroup StateMachine
* \~\brief
* \~english State machine transition
* \~russian Переход машины состояний
*/
//! \~\file pistatemachine_transition.h
//! \~\ingroup StateMachine
//! \~\brief
//! \~english Declares transitions used by PIStateMachine
//! \~russian Объявляет переходы, используемые в PIStateMachine
/*
PIP - Platform Independent Primitives
State machine transition
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
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
@@ -30,22 +29,47 @@
#include "pitimer.h"
//! \ingroup StateMachine
//! \~\ingroup StateMachine
//! \~\brief
//! \~english Transition between states in PIStateMachine.
//! \~russian Переход между состояниями в PIStateMachine.
//! \~\details
//! \~english
//! A transition can be triggered by an event or by a timeout. Optional guards are
//! evaluated against arguments passed to \a PIStateMachine::postEvent().
//! \~russian
//! Переход может запускаться событием или таймаутом. Необязательные guard-функции
//! проверяются на аргументах, переданных в \a PIStateMachine::postEvent().
class PIP_EXPORT PITransitionBase {
friend class PIStateMachine;
friend class PIStateBase;
public:
//! \~english Creates a transition from \a source to \a target for the specified event identifier.
//! \~russian Создает переход из \a source в \a target для указанного идентификатора события.
PITransitionBase(PIStateBase * source, PIStateBase * target, int event_id);
//! \~english Destroys the transition and its stored guard.
//! \~russian Уничтожает переход и сохраненную guard-функцию.
virtual ~PITransitionBase();
//! \~english Returns the root state machine.
//! \~russian Возвращает корневую машину состояний.
PIStateMachine * machine() const { return root; }
//! \~english Returns the source state.
//! \~russian Возвращает исходное состояние.
PIStateBase * source() const { return source_state; }
//! \~english Returns the target state.
//! \~russian Возвращает целевое состояние.
PIStateBase * target() const { return target_state; }
//! \~english Sets a guard function that must return bool.
//! \~russian Задает guard-функцию, которая должна возвращать bool.
template<typename R, typename... Args>
PITransitionBase * addGuard(std::function<R(Args...)> f) {
static_assert(std::is_same<R, bool>::value, "guard function should return bool!");
@@ -54,11 +78,15 @@ public:
return this;
}
//! \~english Sets a guard from a lambda or other callable object.
//! \~russian Задает guard-функцию из lambda или другого вызываемого объекта.
template<typename L>
PITransitionBase * addGuard(L f) {
return addGuard(toStdFunction(f));
}
//! \~english Tests the guard against event arguments passed to the transition.
//! \~russian Проверяет guard-функцию на аргументах события, переданных переходу.
template<typename... Args>
bool testGuard(Args... args) {
if (!guard) return true;
@@ -69,11 +97,20 @@ public:
return reinterpret_cast<PIStateMachineHelpers::Function<Args...> *>(guard)->func(args...);
}
//! \~english Sets an action executed when the transition fires.
//! \~russian Задает действие, выполняемое при срабатывании перехода.
PITransitionBase * addAction(std::function<void()> a);
//! \~english Executes the transition action if it is set.
//! \~russian Выполняет действие перехода, если оно задано.
void makeAction();
//! \~english Triggers the transition and updates active states.
//! \~russian Запускает переход и обновляет активные состояния.
void trigger();
protected:
virtual void enabled() {}
virtual void disabled() {}
@@ -86,11 +123,21 @@ protected:
};
//! \~\ingroup StateMachine
//! \~\brief
//! \~english Transition that fires automatically after a timeout.
//! \~russian Переход, который автоматически срабатывает по истечении таймаута.
class PIP_EXPORT PITransitionTimeout: public PITransitionBase {
public:
//! \~english Creates a transition that fires after \a timeout while the source state is active.
//! \~russian Создает переход, который срабатывает через \a timeout, пока исходное состояние активно.
PITransitionTimeout(PIStateBase * source, PIStateBase * target, PISystemTime timeout);
//! \~english Stops the internal timer and destroys the transition.
//! \~russian Останавливает внутренний таймер и уничтожает переход.
~PITransitionTimeout();
private:
void enabled() override;
void disabled() override;

View File

@@ -1,7 +1,12 @@
//! \file pistatemachinemodule.h
//! \ingroup StateMachine
//! \~\brief
//! \~english Declares module entry includes for the state machine API
//! \~russian Объявляет основной include модуля API машины состояний
/*
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
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
@@ -34,16 +39,19 @@
//! \~russian \par Общее
//!
//! \~english
//!
//! The module provides hierarchical states, event-driven transitions, timeout
//! transitions and helper state classes for callback-based logic.
//! Details in \ref state_machine
//! \~russian
//! Модуль предоставляет иерархические состояния, переходы по событиям,
//! переходы по таймауту и вспомогательные классы состояний для логики на callback-функциях.
//! Подробнее \ref state_machine
//!
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//!
#ifndef PISTATEMACHINEMODULE_H