From e27d5cb1f7fbea7b0001a98ce215f1c3842967c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel=20Gonz=C3=A1lez=20Santamarta?= Date: Mon, 4 Nov 2024 16:26:29 +0100 Subject: [PATCH] validated flag for state machine --- yasmin/include/yasmin/state_machine.hpp | 38 ++++++++++++++++--------- yasmin/src/yasmin/state_machine.cpp | 11 +++++++ yasmin/yasmin/state_machine.py | 13 +++++++++ 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/yasmin/include/yasmin/state_machine.hpp b/yasmin/include/yasmin/state_machine.hpp index e67fc96..fd64463 100644 --- a/yasmin/include/yasmin/state_machine.hpp +++ b/yasmin/include/yasmin/state_machine.hpp @@ -16,6 +16,7 @@ #ifndef YASMIN_STATE_MACHINE_HPP #define YASMIN_STATE_MACHINE_HPP +#include #include #include #include @@ -40,14 +41,16 @@ namespace yasmin { */ class StateMachine : public State { - // Type definitions for callback functions + /// Alias for a callback function executed before running the state machine. using StartCallbackType = std::function, const std::string &, const std::vector &)>; + /// Alias for a callback function executed before changing the state. using TransitionCallbackType = std::function, const std::string &, const std::string &, const std::string &, const std::vector &)>; + /// Alias for a callback function executed after running the state machine. using EndCallbackType = std::function, const std::string &, const std::vector &)>; @@ -225,20 +228,27 @@ class StateMachine : public State { std::string to_string(); private: - std::map> states; ///< Map of states - std::map> - transitions; ///< Map of transitions - std::string start_state; ///< Name of the start state - std::string current_state; ///< Name of the current state - std::unique_ptr - current_state_mutex; ///< Mutex for current state access - - std::vector>> - start_cbs; ///< Start callbacks + /// Map of states + std::map> states; + /// Map of transitions + std::map> transitions; + /// Name of the start state + std::string start_state; + /// Name of the current state + std::string current_state; + /// Mutex for current state access + std::unique_ptr current_state_mutex; + + /// Flag to indicate if the state machine has been validated + std::atomic_bool validated{false}; + + /// Start callbacks executed before the state machine + std::vector>> start_cbs; + /// Transition callbacks executed before changing the state std::vector>> - transition_cbs; ///< Transition callbacks - std::vector>> - end_cbs; ///< End callbacks + transition_cbs; + /// End callbacks executed before the state machine + std::vector>> end_cbs; }; } // namespace yasmin diff --git a/yasmin/src/yasmin/state_machine.cpp b/yasmin/src/yasmin/state_machine.cpp index eeb5832..262db59 100644 --- a/yasmin/src/yasmin/state_machine.cpp +++ b/yasmin/src/yasmin/state_machine.cpp @@ -85,6 +85,9 @@ void StateMachine::add_state(std::string name, std::shared_ptr state, if (this->start_state.empty()) { this->set_start_state(name); } + + // Mark state machine as no validated + this->validated.store(false); } void StateMachine::add_state(std::string name, std::shared_ptr state) { @@ -194,6 +197,11 @@ void StateMachine::validate() { YASMIN_LOG_DEBUG("Validating state machine '%s'", this->to_string().c_str()); + if (this->validated.load()) { + YASMIN_LOG_DEBUG("State machine '%s' has already been validated", + this->to_string().c_str()); + } + // Check initial state if (this->start_state.empty()) { throw std::runtime_error("No initial state set"); @@ -260,6 +268,9 @@ void StateMachine::validate() { "' not registered as outcome or state"); } } + + // State machine has been validated + this->validated.store(true); } std::string diff --git a/yasmin/yasmin/state_machine.py b/yasmin/yasmin/state_machine.py index 4cd0289..a8a61e6 100644 --- a/yasmin/yasmin/state_machine.py +++ b/yasmin/yasmin/state_machine.py @@ -54,6 +54,10 @@ def __init__(self, outcomes: Set[str]) -> None: self.__current_state: str = None ## A threading lock to manage access to the current state. self.__current_state_lock: Lock = Lock() + + ## A flag indicating whether the state machine has been validated. + self._validated: bool = False + ## A list of callbacks to call when the state machine starts. self.__start_cbs: List[ Tuple[Callable[[Blackboard, str, List[Any]], None], List[Any]] @@ -119,6 +123,9 @@ def add_state( if not self._start_state: self.set_start_state(name) + ## Mark state machine as no validated + self._validated = False + def set_start_state(self, state_name: str) -> None: """ Sets the initial state for the state machine. @@ -276,6 +283,9 @@ def validate(self) -> None: """ yasmin.YASMIN_LOG_DEBUG(f"Validating state machine '{self}'") + if self._validated: + yasmin.YASMIN_LOG_DEBUG("State machine '{self}' has already been validated") + # terminal outcomes terminal_outcomes = [] @@ -323,6 +333,9 @@ def validate(self) -> None: f"State machine outcome '{o}' not registered as outcome neither state" ) + # State machine has been validated + self._validated = True + def execute(self, blackboard: Blackboard) -> str: """ Executes the state machine starting from the initial state.