Files
pip/libs/main/state_machine/pistatemachinemodule.h
2026-03-12 14:46:57 +03:00

708 lines
34 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*! \file pistatemachinemodule.h
* \ingroup StateMachine
* \~\brief
* \~english Declares module entry includes for the state machine API
* \~russian Объявляет основной include модуля API машины состояний
*
* \~\details
* \~english Includes the public state machine, state, and transition headers.
* \~russian Подключает публичные заголовки машины состояний, состояний и переходов.
*/
/*
PIP - Platform Independent Primitives
Module includes
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/>.
*/
//! \defgroup StateMachine StateMachine
//! \~\brief
//! \~english State machine.
//! \~russian Машина состояний.
//!
//! \~\details
//! \~english \section cmake_module_StateMachine Building with CMake
//! \~russian \section cmake_module_StateMachine Сборка с использованием CMake
//!
//! \~\code
//! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP)
//! \endcode
//!
//! \~english \par Common
//! \~russian \par Общее
//!
//! \~english
//! The module provides hierarchical states, event-driven transitions, timeout
//! transitions and helper state classes for callback-based logic.
//! \~russian
//! Модуль предоставляет иерархические состояния, переходы по событиям,
//! переходы по таймауту и вспомогательные классы состояний для логики на callback-функциях.
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//!
//!
//! \~english \section state_machine_overview General Description
//! \~russian \section state_machine_overview Общее описание
//!
//! \~english State machine is a behavioral design pattern that allows an object to change its behavior when its internal state changes.
//! Implementation in PIP is based on the **SCXML** (State Chart XML) standard.
//! \~russian Машина состояний — это поведенческий паттерн проектирования, который позволяет объекту изменять свое поведение при изменении
//! внутреннего состояния. Реализация в PIP основана на стандарте **SCXML** (State Chart XML).
//!
//! \~english \subsection scxml_concepts SCXML Concepts
//! \~russian \subsection scxml_concepts Основные концепции SCXML
//!
//! \~english - **State** — a node in the state tree, can be atomic or compound
//! \~russian - **State (Состояние)** — узел в дереве состояний, может быть атомарным или составным
//! \~english - **Transition** — a connection between states that triggers on an event
//! \~russian - **Transition (Переход)** — связь между состояниями, срабатывает при событии
//! \~english - **Event** — a trigger that causes a transition
//! \~russian - **Event (Событие)** — триггер, вызывающий переход
//! \~english - **Guard** — a condition that must be true for a transition to execute
//! \~russian - **Guard (Сторожевая функция)** — условие, которое должно быть истинным для выполнения перехода
//! \~english - **Action** — an operation executed during a transition
//! \~russian - **Action (Действие)** — операция, выполняемая при переходе
//! \~english - **Parallel** — a state where all substates are activated simultaneously
//! \~russian - **Parallel (Параллельное состояние)** — состояние, в котором все подсостояния активируются одновременно
//!
//! \~english \subsection pim_state_machine_features PIP State Machine Features
//! \~russian \subsection pim_state_machine_features Особенности реализации PIP
//!
//! \~english - **Cannot create state, event, transition on stack** — all objects are created via `new` and managed via pointers
//! \~russian - **Нельзя создавать state, event, transition в стеке** — все объекты создаются через `new` и управляются через указатели
//! \~english - **State machine is the root state** — `PIStateMachine` inherits from `PIStateBase`
//! \~russian - **Машина состояний — это корневой state** — `PIStateMachine` наследуется от `PIStateBase`
//! \~english - **All transitions and states are automatically deleted** — when the parent object is destroyed
//! \~russian - **Все переходы и состояния удаляются автоматически** — при уничтожении родительского объекта
//!
//! \~english \subsection state_types State Types
//! \~russian \subsection state_types Основные типы состояний
//!
//! \~english - **Atomic state** — a state without nested substates
//! \~russian - **Атомарное состояние** — состояние без вложенных подсостояний
//! \~english - **Compound state** — a state containing nested substates
//! \~russian - **Составное состояние** — состояние, содержащее вложенные подсостояния
//! \~english - **Final state** — a terminating state indicating the end of machine execution
//! \~russian - **Финальное состояние** — завершающее состояние, указывающее на окончание работы машины
//! \~english - **Parallel state** — a state where all substates are activated simultaneously
//! \~russian - **Параллельное состояние** — состояние, в котором все подсостояния активируются одновременно
//!
//! \~english \subsection transition_types Transition Types
//! \~russian \subsection transition_types Виды переходов
//!
//! \~english - **Normal transition** — triggers on receiving a specific event
//! \~russian - **Обычный переход** — срабатывает при получении определенного события
//! \~english - **Timeout transition** — triggers automatically after a specified time interval
//! \~russian - **Переход по таймауту** — срабатывает автоматически через заданный промежуток времени
//! \~english - **Guarded transition** — triggers only when a specific condition is met
//! \~russian - **Переход с guard** — срабатывает только при выполнении определенного условия
//!
//! \~english \section state_machine_api State Machine API
//! \~russian \section state_machine_api PIP State Machine API
//!
//! \~english \subsection main_classes Main Classes
//! \~russian \subsection main_classes Основные классы
//!
//! \~english ### PIStateMachine
//!
//! \~english Main state machine class.
//! \~russian Основной класс машины состояний.
//!
//! \~english **Key methods:**
//! \~russian **Ключевые методы:**
//!
//! \~english - `bool start()` — starts state machine execution
//! \~russian - `bool start()` — запускает выполнение машины состояний
//! \~english - `bool isRunning()` — checks if state machine is running
//! \~russian - `bool isRunning()` — проверяет, запущена ли машина
//! \~english - `void setOnFinish(std::function<void()> f)` — sets finish callback
//! \~russian - `void setOnFinish(std::function<void()> f)` — устанавливает коллбэк завершения
//! \~english - `bool postEvent(int event_id, Args... args)` — posts event to state machine
//! \~russian - `bool postEvent(int event_id, Args... args)` — отправляет событие в машину состояний
//!
//! \~english ### PIStateBase
//!
//! \~english Base class for all states.
//! \~russian Базовый класс для всех состояний.
//!
//! \~english **Key methods:**
//! \~russian **Ключевые методы:**
//!
//! \~english - `virtual void onEnter()` — called when state is entered
//! \~russian - `virtual void onEnter()` — вызывается при входе в состояние
//! \~english - `virtual void onExit()` — called when state is exited
//! \~russian - `virtual void onExit()` — вызывается при выходе из состояния
//! \~english - `void addState(PIStateBase *s)` — adds child state
//! \~russian - `void addState(PIStateBase *s)` — добавляет дочернее состояние
//! \~english - `PITransitionBase *addTransition(PIStateBase *target, int event_id)` — adds transition
//! \~russian - `PITransitionBase *addTransition(PIStateBase *target, int event_id)` — добавляет переход
//! \~english - `PITransitionTimeout *addTimeoutTransition(PIStateBase *target, PISystemTime timeout)` — adds timeout transition
//! \~russian - `PITransitionTimeout *addTimeoutTransition(PIStateBase *target, PISystemTime timeout)` — добавляет переход по таймауту
//! \~english - `void setParallel(bool yes)` — sets parallel mode
//! \~russian - `void setParallel(bool yes)` — устанавливает параллельный режим
//!
//! \~english ### PIStateLambda
//!
//! \~english State with lambda callbacks.
//! \~russian Состояние с lambda-коллбэками.
//!
//! \~english ```cpp
//! \~english PIStateLambda(std::function<void()> on_enter, std::function<void()> on_exit = nullptr, const PIString &n = {})
//! \~english ```
//! \~russian ```cpp
//! \~russian PIStateLambda(std::function<void()> on_enter, std::function<void()> on_exit = nullptr, const PIString &n = {})
//! \~russian ```
//!
//! \~english ### PIStateFinal
//!
//! \~english Final state of state machine.
//! \~russian Финальное состояние машины состояний.
//!
//! \~english ```cpp
//! \~english PIStateFinal(std::function<void()> on_finish = nullptr, const PIString &n = {})
//! \~english ```
//! \~russian ```cpp
//! \~russian PIStateFinal(std::function<void()> on_finish = nullptr, const PIString &n = {})
//! \~russian ```
//!
//! \~english ### PITransitionBase
//!
//! \~english Base class for transitions.
//! \~russian Базовый класс для переходов.
//!
//! \~english **Key methods:**
//! \~russian **Ключевые методы:**
//!
//! \~english - `PITransitionBase *addGuard(std::function<R(Args...)> f)` — adds guard function
//! \~russian - `PITransitionBase *addGuard(std::function<R(Args...)> f)` — добавляет сторожевую функцию
//! \~english - `PITransitionBase *addAction(std::function<void()> a)` — adds action
//! \~russian - `PITransitionBase *addAction(std::function<void()> a)` — добавляет действие
//! \~english - `void trigger()` — triggers transition
//! \~russian - `void trigger()` — запускает переход
//!
//! \~english ### PITransitionTimeout
//!
//! \~english Transition that triggers after a specified timeout.
//! \~russian Переход, срабатывающий через заданный промежуток времени.
//!
//! \~english \section usage_examples Usage Examples
//! \~russian \section usage_examples Примеры использования
//!
//! \~english \subsection simple_state_machine Simple State Machine
//! \~russian \subsection simple_state_machine Простая машина состояний
//!
//! \~english ```cpp
//! \~english #include "pistatemachine.h"
//! \~english #include "pisystemtime.h"
//! \~english
//! \~english // Create state machine
//! \~english PIStateMachine *machine = new PIStateMachine("Main");
//! \~english
//! \~english // Create states
//! \~english PIStateLambda *idle = new PIStateLambda(
//! \~english []() { piCout << "Entering Idle state\n"; },
//! \~english []() { piCout << "Exiting Idle state\n"; },
//! \~english "Idle"
//! \~english );
//! \~english PIStateLambda *running = new PIStateLambda(
//! \~english []() { piCout << "Entering Running state\n"; },
//! \~english []() { piCout << "Exiting Running state\n"; },
//! \~english "Running"
//! \~english );
//! \~english PIStateFinal *finish = new PIStateFinal(
//! \~english []() { piCout << "Machine finished\n"; },
//! \~english "Finish"
//! \~english );
//! \~english
//! \~english // Add states
//! \~english machine->addState(idle);
//! \~english machine->addState(running);
//! \~english machine->addState(finish);
//! \~english
//! \~english // Set initial state
//! \~english idle->setInitialState(idle);
//! \~english running->setInitialState(running);
//! \~english machine->setInitialState(idle);
//! \~english
//! \~english // Add transitions
//! \~english idle->addTransition(running, 1);
//! \~english running->addTransition(finish, 2);
//! \~english
//! \~english // Set finish callback
//! \~english machine->setOnFinish([]() { piCout << "Machine execution completed\n"; });
//! \~english
//! \~english // Start machine
//! \~english machine->start();
//! \~english
//! \~english // Post events
//! \~english machine->postEvent(1); // Transition to Running
//! \~english machine->postEvent(2); // Transition to Finish
//! \~english ```
//! \~russian ```cpp
//! \~russian #include "pistatemachine.h"
//! \~russian #include "pisystemtime.h"
//! \~russian
//! \~russian // Создаем машину состояний
//! \~russian PIStateMachine *machine = new PIStateMachine("Main");
//! \~russian
//! \~russian // Создаем состояния
//! \~russian PIStateLambda *idle = new PIStateLambda(
//! \~russian []() { piCout << "Entering Idle state\n"; },
//! \~russian []() { piCout << "Exiting Idle state\n"; },
//! \~russian "Idle"
//! \~russian );
//! \~russian PIStateLambda *running = new PIStateLambda(
//! \~russian []() { piCout << "Entering Running state\n"; },
//! \~russian []() { piCout << "Exiting Running state\n"; },
//! \~russian "Running"
//! \~russian );
//! \~russian PIStateFinal *finish = new PIStateFinal(
//! \~russian []() { piCout << "Machine finished\n"; },
//! \~russian "Finish"
//! \~russian );
//! \~russian
//! \~russian // Добавляем состояния
//! \~russian machine->addState(idle);
//! \~russian machine->addState(running);
//! \~russian machine->addState(finish);
//! \~russian
//! \~russian // Устанавливаем начальное состояние
//! \~russian idle->setInitialState(idle);
//! \~russian running->setInitialState(running);
//! \~russian machine->setInitialState(idle);
//! \~russian
//! \~russian // Добавляем переходы
//! \~russian idle->addTransition(running, 1);
//! \~russian running->addTransition(finish, 2);
//! \~russian
//! \~russian // Устанавливаем коллбэк завершения
//! \~russian machine->setOnFinish([]() { piCout << "Machine execution completed\n"; });
//! \~russian
//! \~russian // Запускаем машину
//! \~russian machine->start();
//! \~russian
//! \~russian // Отправляем события
//! \~russian machine->postEvent(1); // Перейти в Running
//! \~russian machine->postEvent(2); // Перейти в Finish
//! \~russian ```
//!
//! \~english \subsection guarded_transitions Guarded Transitions
//! \~russian \subsection guarded_transitions Машина состояний с guard-функциями
//!
//! \~english ```cpp
//! \~english PIStateMachine *machine = new PIStateMachine("With Guards");
//! \~english
//! \~english PIStateLambda *stateA = new PIStateLambda([]() { piCout << "State A\n"; }, nullptr, "A");
//! \~english PIStateLambda *stateB = new PIStateLambda([]() { piCout << "State B\n"; }, nullptr, "B");
//! \~english PIStateLambda *stateC = new PIStateLambda([]() { piCout << "State C\n"; }, nullptr, "C");
//! \~english
//! \~english machine->addState(stateA);
//! \~english machine->addState(stateB);
//! \~english machine->addState(stateC);
//! \~english
//! \~english stateA->setInitialState(stateA);
//! \~english machine->setInitialState(stateA);
//! \~english
//! \~english // Transition with guard function
//! \~english auto *t1 = stateA->addTransition(stateB, 1);
//! \~english t1->addGuard([](int value) -> bool {
//! \~english return value > 10;
//! \~english });
//! \~english
//! \~english // Transition with another guard function
//! \~english auto *t2 = stateB->addTransition(stateC, 2);
//! \~english t2->addGuard([](const PIString &msg) -> bool {
//! \~english return msg == "allowed";
//! \~english });
//! \~english
//! \~english machine->start();
//! \~english
//! \~english // First call will not execute (value <= 10)
//! \~english machine->postEvent(1, 5);
//! \~english
//! \~english // Second call will execute (value > 10)
//! \~english machine->postEvent(1, 15);
//! \~english
//! \~english // First call will not execute (msg != "allowed")
//! \~english machine->postEvent(2, "test");
//! \~english
//! \~english // Second call will execute (msg == "allowed")
//! \~english machine->postEvent(2, "allowed");
//! \~english ```
//! \~russian ```cpp
//! \~russian PIStateMachine *machine = new PIStateMachine("With Guards");
//! \~russian
//! \~russian PIStateLambda *stateA = new PIStateLambda([]() { piCout << "State A\n"; }, nullptr, "A");
//! \~russian PIStateLambda *stateB = new PIStateLambda([]() { piCout << "State B\n"; }, nullptr, "B");
//! \~russian PIStateLambda *stateC = new PIStateLambda([]() { piCout << "State C\n"; }, nullptr, "C");
//! \~russian
//! \~russian machine->addState(stateA);
//! \~russian machine->addState(stateB);
//! \~russian machine->addState(stateC);
//! \~russian
//! \~russian stateA->setInitialState(stateA);
//! \~russian machine->setInitialState(stateA);
//! \~russian
//! \~russian // Переход с guard-функцией
//! \~russian auto *t1 = stateA->addTransition(stateB, 1);
//! \~russian t1->addGuard([](int value) -> bool {
//! \~russian return value > 10;
//! \~russian });
//! \~russian
//! \~russian // Переход с другой guard-функцией
//! \~russian auto *t2 = stateB->addTransition(stateC, 2);
//! \~russian t2->addGuard([](const PIString &msg) -> bool {
//! \~russian return msg == "allowed";
//! \~russian });
//! \~russian
//! \~russian machine->start();
//! \~russian
//! \~russian // Первый вызов не выполнится (value <= 10)
//! \~russian machine->postEvent(1, 5);
//! \~russian
//! \~russian // Второй вызов выполнится (value > 10)
//! \~russian machine->postEvent(1, 15);
//! \~russian
//! \~russian // Первый вызов не выполнится (msg != "allowed")
//! \~russian machine->postEvent(2, "test");
//! \~russian
//! \~russian // Второй вызов выполнится (msg == "allowed")
//! \~russian machine->postEvent(2, "allowed");
//! \~russian ```
//!
//! \~english \subsection timeout_transitions Timeout Transitions
//! \~russian \subsection timeout_transitions Машина состояний с таймаутами
//!
//! \~english ```cpp
//! \~english PIStateMachine *machine = new PIStateMachine("With Timeout");
//! \~english
//! \~english PIStateLambda *working = new PIStateLambda(
//! \~english []() { piCout << "Working...\n"; },
//! \~english []() { piCout << "Stop working\n"; },
//! \~english "Working"
//! \~english );
//! \~english PIStateLambda *timeoutState = new PIStateLambda([]() { piCout << "Timeout occurred\n"; }, nullptr, "Timeout");
//! \~english PIStateFinal *finish = new PIStateFinal([]() { piCout << "Done\n"; }, "Finish");
//! \~english
//! \~english machine->addState(working);
//! \~english machine->addState(timeoutState);
//! \~english machine->addState(finish);
//! \~english
//! \~english working->setInitialState(working);
//! \~english machine->setInitialState(working);
//! \~english
//! \~english // Add timeout transition (after 5 seconds)
//! \~english working->addTimeoutTransition(timeoutState, PISystemTime::fromSeconds(5));
//! \~english
//! \~english // Add transition from timeoutState to finish
//! \~english timeoutState->addTransition(finish, 1);
//! \~english
//! \~english machine->start();
//! \~english ```
//! \~russian ```cpp
//! \~russian PIStateMachine *machine = new PIStateMachine("With Timeout");
//! \~russian
//! \~russian PIStateLambda *working = new PIStateLambda(
//! \~russian []() { piCout << "Working...\n"; },
//! \~russian []() { piCout << "Stop working\n"; },
//! \~russian "Working"
//! \~russian );
//! \~russian PIStateLambda *timeoutState = new PIStateLambda([]() { piCout << "Timeout occurred\n"; }, nullptr, "Timeout");
//! \~russian PIStateFinal *finish = new PIStateFinal([]() { piCout << "Done\n"; }, "Finish");
//! \~russian
//! \~russian machine->addState(working);
//! \~russian machine->addState(timeoutState);
//! \~russian machine->addState(finish);
//! \~russian
//! \~russian working->setInitialState(working);
//! \~russian machine->setInitialState(working);
//! \~russian
//! \~russian // Добавляем переход по таймауту (через 5 секунд)
//! \~russian working->addTimeoutTransition(timeoutState, PISystemTime::fromSeconds(5));
//! \~russian
//! \~russian // Добавляем переход из timeoutState в finish
//! \~russian timeoutState->addTransition(finish, 1);
//! \~russian
//! \~russian machine->start();
//! \~russian ```
//!
//! \~english \subsection compound_states Compound States
//! \~russian \subsection compound_states Составные состояния
//!
//! \~english ```cpp
//! \~english PIStateMachine *machine = new PIStateMachine("Compound States");
//! \~english
//! \~english // Root state (machine)
//! \~english PIStateLambda *root = new PIStateLambda([]() { piCout << "Root state\n"; }, nullptr, "Root");
//! \~english
//! \~english // Compound state with substates
//! \~english PIStateLambda *parent = new PIStateLambda([]() { piCout << "Parent state\n"; }, nullptr, "Parent");
//! \~english PIStateLambda *child1 = new PIStateLambda([]() { piCout << "Child 1\n"; }, nullptr, "Child1");
//! \~english PIStateLambda *child2 = new PIStateLambda([]() { piCout << "Child 2\n"; }, nullptr, "Child2");
//! \~english
//! \~english parent->setInitialState(child1);
//! \~english parent->addState(child1);
//! \~english parent->addState(child2);
//! \~english root->addState(parent);
//! \~english
//! \~english machine->addState(root);
//! \~english machine->setInitialState(root);
//! \~english
//! \~english // Add transitions
//! \~english root->addTransition(parent, 1);
//! \~english parent->addTransition(root, 2);
//! \~english
//! \~english machine->start();
//! \~english
//! \~english // Transition to parent
//! \~english machine->postEvent(1);
//! \~english
//! \~english // Transition back
//! \~english machine->postEvent(2);
//! \~english ```
//! \~russian ```cpp
//! \~russian PIStateMachine *machine = new PIStateMachine("Compound States");
//! \~russian
//! \~russian // Корневое состояние (машина)
//! \~russian PIStateLambda *root = new PIStateLambda([]() { piCout << "Root state\n"; }, nullptr, "Root");
//! \~russian
//! \~russian // Составное состояние с подсостояниями
//! \~russian PIStateLambda *parent = new PIStateLambda([]() { piCout << "Parent state\n"; }, nullptr, "Parent");
//! \~russian PIStateLambda *child1 = new PIStateLambda([]() { piCout << "Child 1\n"; }, nullptr, "Child1");
//! \~russian PIStateLambda *child2 = new PIStateLambda([]() { piCout << "Child 2\n"; }, nullptr, "Child2");
//! \~russian
//! \~russian parent->setInitialState(child1);
//! \~russian parent->addState(child1);
//! \~russian parent->addState(child2);
//! \~russian root->addState(parent);
//! \~russian
//! \~russian machine->addState(root);
//! \~russian machine->setInitialState(root);
//! \~russian
//! \~russian // Добавляем переходы
//! \~russian root->addTransition(parent, 1);
//! \~russian parent->addTransition(root, 2);
//! \~russian
//! \~russian machine->start();
//! \~russian
//! \~russian // Переход в parent
//! \~russian machine->postEvent(1);
//! \~russian
//! \~russian // Переход обратно
//! \~russian machine->postEvent(2);
//! \~russian ```
//!
//! \~english \subsection parallel_states Parallel States
//! \~russian \subsection parallel_states Параллельные состояния
//!
//! \~english ```cpp
//! \~english PIStateMachine *machine = new PIStateMachine("Parallel States");
//! \~english
//! \~english PIStateLambda *root = new PIStateLambda([]() { piCout << "Root\n"; }, nullptr, "Root");
//! \~english PIStateLambda *parallel = new PIStateLambda([]() { piCout << "Parallel\n"; }, nullptr, "Parallel");
//! \~english PIStateLambda *sub1 = new PIStateLambda([]() { piCout << "Substate 1\n"; }, nullptr, "Sub1");
//! \~english PIStateLambda *sub2 = new PIStateLambda([]() { piCout << "Substate 2\n"; }, nullptr, "Sub2");
//! \~english
//! \~english // Enable parallel mode
//! \~english parallel->setParallel(true);
//! \~english parallel->addState(sub1);
//! \~english parallel->addState(sub2);
//! \~english parallel->setInitialState(sub1);
//! \~english root->addState(parallel);
//! \~english
//! \~english machine->addState(root);
//! \~english machine->setInitialState(root);
//! \~english
//! \~english machine->start();
//! \~english
//! \~english // When entering parallel, both substates are activated simultaneously
//! \~english ```
//! \~russian ```cpp
//! \~russian PIStateMachine *machine = new PIStateMachine("Parallel States");
//! \~russian
//! \~russian PIStateLambda *root = new PIStateLambda([]() { piCout << "Root\n"; }, nullptr, "Root");
//! \~russian PIStateLambda *parallel = new PIStateLambda([]() { piCout << "Parallel\n"; }, nullptr, "Parallel");
//! \~russian PIStateLambda *sub1 = new PIStateLambda([]() { piCout << "Substate 1\n"; }, nullptr, "Sub1");
//! \~russian PIStateLambda *sub2 = new PIStateLambda([]() { piCout << "Substate 2\n"; }, nullptr, "Sub2");
//! \~russian
//! \~russian // Включаем параллельный режим
//! \~russian parallel->setParallel(true);
//! \~russian parallel->addState(sub1);
//! \~russian parallel->addState(sub2);
//! \~russian parallel->setInitialState(sub1);
//! \~russian root->addState(parallel);
//! \~russian
//! \~russian machine->addState(root);
//! \~russian machine->setInitialState(root);
//! \~russian
//! \~russian machine->start();
//! \~russian
//! \~russian // При входе в parallel оба подсостояния активируются одновременно
//! \~russian ```
//!
//! \~english \subsection transitions_with_actions Transitions with Actions
//! \~russian \subsection transitions_with_actions Машина состояний с действиями
//!
//! \~english ```cpp
//! \~english PIStateMachine *machine = new PIStateMachine("With Actions");
//! \~english
//! \~english PIStateLambda *stateA = new PIStateLambda([]() { piCout << "State A\n"; }, nullptr, "A");
//! \~english PIStateLambda *stateB = new PIStateLambda([]() { piCout << "State B\n"; }, nullptr, "B");
//! \~english
//! \~english machine->addState(stateA);
//! \~english machine->addState(stateB);
//! \~english
//! \~english machine->setInitialState(stateA);
//! \~english
//! \~english // Add transition with action
//! \~english auto *t = stateA->addTransition(stateB, 1);
//! \~english t->addAction([]() { piCout << "Action during transition\n"; });
//! \~english
//! \~english machine->start();
//! \~english machine->postEvent(1);
//! \~english ```
//! \~russian ```cpp
//! \~russian PIStateMachine *machine = new PIStateMachine("With Actions");
//! \~russian
//! \~russian PIStateLambda *stateA = new PIStateLambda([]() { piCout << "State A\n"; }, nullptr, "A");
//! \~russian PIStateLambda *stateB = new PIStateLambda([]() { piCout << "State B\n"; }, nullptr, "B");
//! \~russian
//! \~russian machine->addState(stateA);
//! \~russian machine->addState(stateB);
//! \~russian
//! \~russian machine->setInitialState(stateA);
//! \~russian
//! \~russian // Добавляем переход с действием
//! \~russian auto *t = stateA->addTransition(stateB, 1);
//! \~russian t->addAction([]() { piCout << "Action during transition\n"; });
//! \~russian
//! \~russian machine->start();
//! \~russian machine->postEvent(1);
//! \~russian ```
//!
//! \~english \section threading Thread Safety
//! \~russian \section threading Потокобезопасность
//!
//! \~english State machine is thread-safe. The `postEvent` method uses a queue to handle nested calls, allowing safe event posting from
//! different threads.
//! \~russian Машина состояний PIP потокобезопасна. Метод `postEvent` использует очередь для обработки вложенных вызовов, что позволяет
//! безопасно отправлять события из разных потоков.
//!
//! \~english \section usage_rules Usage Rules
//! \~russian \section usage_rules Правила использования
//!
//! \~english \subsection cannot_stack Cannot Create on Stack
//! \~russian \subsection cannot_stack Нельзя создавать в стеке
//!
//! \~english ```cpp
//! \~english // ❌ WRONG
//! \~english PIStateLambda state([]() {}, nullptr, "State");
//! \~english
//! \~english // ✅ CORRECT
//! \~english PIStateLambda *state = new PIStateLambda([]() {}, nullptr, "State");
//! \~english ```
//! \~russian ```cpp
//! \~russian // ❌ НЕЛЬЗЯ
//! \~russian PIStateLambda state([]() {}, nullptr, "State");
//! \~russian
//! \~russian // ✅ ПРАВИЛЬНО
//! \~russian PIStateLambda *state = new PIStateLambda([]() {}, nullptr, "State");
//! \~russian ```
//!
//! \~english \subsection proper_hierarchy Proper Object Hierarchy
//! \~russian \subsection proper_hierarchy Правильная иерархия объектов
//!
//! \~english ```cpp
//! \~english PIStateMachine *machine = new PIStateMachine("Main");
//! \~english
//! \~english // States are created via new and added to machine or another state
//! \~english PIStateLambda *state1 = new PIStateLambda([]() {}, nullptr, "State1");
//! \~english PIStateLambda *state2 = new PIStateLambda([]() {}, nullptr, "State2");
//! \~english
//! \~english machine->addState(state1);
//! \~english machine->addState(state2);
//! \~english
//! \~english // Transitions are added to states via addTransition
//! \~english state1->addTransition(state2, 1);
//! \~english
//! \~english // Machine is started
//! \~english machine->start();
//! \~english ```
//! \~russian ```cpp
//! \~russian PIStateMachine *machine = new PIStateMachine("Main");
//! \~russian
//! \~russian // Состояния создаются через new и добавляются в машину или другое состояние
//! \~russian PIStateLambda *state1 = new PIStateLambda([]() {}, nullptr, "State1");
//! \~russian PIStateLambda *state2 = new PIStateLambda([]() {}, nullptr, "State2");
//! \~russian
//! \~russian machine->addState(state1);
//! \~russian machine->addState(state2);
//! \~russian
//! \~russian // Переходы добавляются к состояниям через addTransition
//! \~russian state1->addTransition(state2, 1);
//! \~russian
//! \~russian // Машина запускается
//! \~russian machine->start();
//! \~russian ```
//!
//! \~english \subsection memory_cleanup Memory Cleanup
//! \~russian \subsection memory_cleanup Очистка памяти
//!
//! \~english All objects (states, transitions) are automatically deleted when the parent object is destroyed:
//! \~russian Все объекты (состояния, переходы) автоматически удаляются при уничтожении родительского объекта:
//!
//! \~english - When `PIStateMachine` is destroyed, all states and transitions are deleted
//! \~russian - При уничтожении `PIStateMachine` удаляются все состояния и переходы
//! \~english - When `PIStateBase` is destroyed, all child states and transitions are deleted
//! \~russian - При уничтожении `PIStateBase` удаляются все дочерние состояния и переходы
//!
//! \~english \section debugging Debugging
//! \~russian \section debugging Отладка
//!
//! \~english For debugging, you can use the `print()` method to output the state tree:
//! \~russian Для отладки можно использовать метод `print()` для вывода дерева состояний:
//!
//! \~english ```cpp
//! \~english machine->print();
//! \~english ```
//! \~russian ```cpp
//! \~russian machine->print();
//! \~russian ```
//!
//! \~english Also, you can use `activeAtomics()` to get a list of active states.
//! \~russian Также можно использовать `activeAtomics()` для получения списка активных состояний.
//!
//! \~english \section related_modules Related Modules
//! \~russian \section related_modules Связанные модули
//!
//! \~english - \ref DateTime module for `PISystemTime` used in timeout transitions
//! \~russian - \ref DateTime модуль для `PISystemTime`, используемого в переходах по таймауту
//!
//! \~\}
#ifndef PISTATEMACHINEMODULE_H
#define PISTATEMACHINEMODULE_H
#include "pistatemachine.h"
#include "pistatemachine_state.h"
#include "pistatemachine_transition.h"
#endif