// Copyright 2025 Christian Granzin // Copyright 2008 Christophe Henry // henry UNDERSCORE christophe AT hotmail DOT com // This is an extended version of the state machine available in the boost::mpl library // Distributed under the same license as the original. // Copyright for the original version: // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed // under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include "boost/msm/back/state_machine.hpp" #include "boost/msm/backmp11/state_machine_config.hpp" #include "boost/msm/backmp11/favor_compile_time.hpp" #include "boost/msm/backmp11/state_machine.hpp" #include #define BOOST_PARAMETER_CAN_USE_MP11 #include #include #include #include "Backmp11.hpp" namespace boost::msm::backmp11 { using back::queue_container_deque; template < class A1, class A2, class A3, class A4 > struct state_machine_config_adapter : state_machine_config { typedef ::boost::parameter::parameters< ::boost::parameter::optional< ::boost::parameter::deduced< back::tag::history_policy>, has_history_policy< ::boost::mpl::_ > > , ::boost::parameter::optional< ::boost::parameter::deduced< back::tag::compile_policy>, has_compile_policy< ::boost::mpl::_ > > , ::boost::parameter::optional< ::boost::parameter::deduced< back::tag::fsm_check_policy>, has_fsm_check< ::boost::mpl::_ > > , ::boost::parameter::optional< ::boost::parameter::deduced< back::tag::queue_container_policy>, has_queue_container_policy< ::boost::mpl::_ > > > config_signature; typedef typename config_signature::bind::type config_args; typedef typename ::boost::parameter::binding< config_args, back::tag::compile_policy, favor_runtime_speed >::type CompilePolicy; using compile_policy = mp11::mp_if_c< std::is_same_v, favor_runtime_speed, favor_compile_time>; typedef typename ::boost::parameter::binding< config_args, back::tag::queue_container_policy, queue_container_deque >::type QueueContainerPolicy; template using queue_container = typename QueueContainerPolicy::template In::type; }; template class state_machine_adapter : public state_machine, state_machine_adapter> { using Base = state_machine, state_machine_adapter>; public: using Base::Base; // The new API returns a const std::array<...>&. const int* current_state() const { return &this->get_active_state_ids()[0]; } // The history can be accessed like this, // but it has to be configured in the front-end. auto& get_history() { return this->m_history; } auto& get_message_queue() { return this->get_events_queue(); } size_t get_message_queue_size() const { return this->get_events_queue().size(); } void execute_queued_events() { this->process_queued_events(); } void execute_single_queued_event() { this->process_single_queued_event(); } auto& get_deferred_queue() { return this->get_deferred_events_queue(); } void clear_deferred_queue() { this->get_deferred_events_queue().clear(); } // No adapter. // Superseded by the visitor API. // void visit_current_states(...) {...} // No adapter. // States can be set with `get_state<...>()` or the visitor API. // void set_states(...) {...} // No adapter. // Could be implemented with the visitor API. // auto get_state_by_id(int id) {...} }; template struct serialize_state { serialize_state(Archive& ar):ar_(ar){} template typename ::boost::enable_if< typename ::boost::mpl::or_< typename has_do_serialize::type, typename detail::has_state_machine_tag::type >::type ,void >::type operator()(T& t) const { ar_ & t; } template typename ::boost::disable_if< typename ::boost::mpl::or_< typename has_do_serialize::type, typename detail::has_state_machine_tag::type >::type ,void >::type operator()(T&) const { // no state to serialize } Archive& ar_; }; namespace detail { template void serialize(Archive& ar, state_machine_base& sm) { (serialize_state(ar))(boost::serialization::base_object(sm)); ar & sm.m_active_state_ids; ar & sm.m_history; ar & sm.m_event_processing; mp11::tuple_for_each(sm.m_states, serialize_state(ar)); } template void serialize(T& ar, detail::history_impl& history) { ar & history.m_initial_state_ids; } template void serialize(T& ar, detail::history_impl, N>& history) { ar & history.m_initial_state_ids; ar & history.m_last_active_state_ids; } } } // boost::msm::backmp11 namespace boost::serialization { template void serialize(Archive& ar, msm::backmp11::state_machine_adapter& sm, const unsigned int /*version*/) { msm::backmp11::detail::serialize(ar, sm); } template void serialize(T& ar, msm::backmp11::detail::history_impl& history, const unsigned int /*version*/) { msm::backmp11::detail::serialize(ar, history); } template void serialize(T& ar, msm::backmp11::detail::history_impl, N>& history, const unsigned int /*version*/) { msm::backmp11::detail::serialize(ar, history); } } // boost::serialization