mirror of
https://github.com/boostorg/msm.git
synced 2026-01-19 04:22:11 +00:00
First backmp11 version (#4)
First version of the backmp11 backend. Contains: - favor_runtime_speed policy that mainly replaces MPL with Mp11 - favor_compile_time that uses a new mechanism with dispatch tables per state
This commit is contained in:
committed by
GitHub
parent
7753fa0170
commit
2d87fa9145
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/.cache
|
||||
/.vscode
|
||||
/build
|
||||
/cmp_*.cpp
|
||||
/format.cpp
|
||||
@@ -6,6 +6,12 @@
|
||||
cmake_minimum_required(VERSION 3.5...3.16)
|
||||
|
||||
project(boost_msm VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
# Temporary settings for development, need to be cleaned up later.
|
||||
# Required for testing puml frontend
|
||||
# set(CMAKE_CXX_STANDARD 20)
|
||||
# Required due to bug in clang19
|
||||
# add_compile_options("-Wno-missing-template-arg-list-after-template-kw")
|
||||
# add_compile_options("-ftime-trace")
|
||||
|
||||
add_library(boost_msm INTERFACE)
|
||||
add_library(Boost::msm ALIAS boost_msm)
|
||||
@@ -34,8 +40,6 @@ target_link_libraries(boost_msm
|
||||
)
|
||||
|
||||
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
|
||||
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
63
include/boost/msm/backmp11/README.md
Normal file
63
include/boost/msm/backmp11/README.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Boost MSM backmp11 backend
|
||||
|
||||
The new backend `backmp11` is a new backwards-compatible backend that has the following goals:
|
||||
|
||||
- reduce compilation runtime and RAM usage
|
||||
- reduce state machine runtime
|
||||
|
||||
It is named after the metaprogramming library Boost Mp11, the main contributor to the optimizations:
|
||||
It replaces usages of MPL with Mp11 to get rid of the C++03 emulation of variadic templates.
|
||||
This backend contains additional optimizations that are further described below.
|
||||
|
||||
|
||||
## How to use it
|
||||
|
||||
The backend and both its policies `favor_runtime_speed` and `favor_compile_time` should be compatible with existing code. Required replacements to try it out:
|
||||
- use `boost::msm::backmp11::state_machine` in place of `boost::msm::back::state_machine` and
|
||||
- use `boost::msm::backmp11::favor_compile_time` in place of `boost::msm::back::favor_compile_time`
|
||||
|
||||
When using the `favor_compile_time` policy, a different macro to generate missing parts of a SM is needed:
|
||||
- use `BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(<fsmname>)` in place of `BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(<fsmname>)`
|
||||
|
||||
|
||||
## General optimizations
|
||||
|
||||
- Replacement of CPU-intensive calls due to C++03 recursion from MPL to Mp11
|
||||
- Applied type punning where useful (to reduce template instantiations, e.g. std::deque & other things around the dispatch table)
|
||||
|
||||
|
||||
## Optimizations applied to the `favor_runtime_speed` policy
|
||||
|
||||
Summary:
|
||||
- Optimized cell initialization with initializer arrays (to reduce template instantiations)
|
||||
- TODO: double-check optimization
|
||||
- Default-initialized everything and afterwards only defer transition cells
|
||||
|
||||
|
||||
## Optimizations applied to the `favor_compile_time` policy
|
||||
|
||||
Once an event is given to the FSM for processing, it is immediately converted to `any` and processing continues with this `any` event.
|
||||
The structure of the dispatch table has been reworked, one dispatch table is created per state as a hash map.
|
||||
The state dispatch tables are designed to directly work with the `any` event, they use the event's type index via its `type()` function as hash value.
|
||||
|
||||
This mechanism enables SMs to forward events to sub-SMs without requiring additional template instantiations just for forwarding as was needed with the `process_any_event` mechanism.
|
||||
The new mechanism renders the `process_any_event` function obsolete and enables **forwarding of events to sub-SMs in O(1) complexity instead of O(N)**.
|
||||
|
||||
Summary:
|
||||
- Use one dispatch table per state to reduce compiler processing time
|
||||
- The algorithms for procesing the STT and states are optimized to go through rows and states only once
|
||||
- These dispatch tables are hash tables with type_id as key
|
||||
- Apply type erasure with boost::any as early as possible and do further processing only with any events
|
||||
- each dispatch table only has to cover the events it's handling, no template instantiations required for forwarding events to sub-SMs
|
||||
- Use `std::any` if C++17 is available (up to 30% runtime impact because of small value optimization in `std::any`)
|
||||
|
||||
|
||||
## Learnings:
|
||||
|
||||
- If only a subset needs to be processed, prefer copy_if & transform over fold
|
||||
- Selecting a template-based function overload in Mp11 seems more efficient than using enable_if/disable_if
|
||||
|
||||
|
||||
## TODOs:
|
||||
|
||||
- Consider trying out the tuple impl from SML
|
||||
38
include/boost/msm/backmp11/common_types.hpp
Normal file
38
include/boost/msm/backmp11/common_types.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_MSM_BACKMP11_COMMON_TYPES_H
|
||||
#define BOOST_MSM_BACKMP11_COMMON_TYPES_H
|
||||
|
||||
#include <boost/msm/back/common_types.hpp>
|
||||
|
||||
namespace boost { namespace msm { namespace backmp11
|
||||
{
|
||||
|
||||
using back::HandledEnum;
|
||||
using back::HANDLED_FALSE;
|
||||
using back::HANDLED_TRUE;
|
||||
using back::HANDLED_GUARD_REJECT;
|
||||
using back::HANDLED_DEFERRED;
|
||||
|
||||
using back::execute_return;
|
||||
|
||||
using back::EVENT_SOURCE_DEFAULT;
|
||||
using back::EVENT_SOURCE_DIRECT;
|
||||
using back::EVENT_SOURCE_DEFERRED;
|
||||
using back::EVENT_SOURCE_MSG_QUEUE;
|
||||
|
||||
using back::EventSource;
|
||||
|
||||
}}} // namespace boost::msm::backmp11
|
||||
|
||||
|
||||
#endif // BOOST_MSM_BACKMP11_COMMON_TYPES_H
|
||||
413
include/boost/msm/backmp11/dispatch_table.hpp
Normal file
413
include/boost/msm/backmp11/dispatch_table.hpp
Normal file
@@ -0,0 +1,413 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_MSM_BACKMP11_DISPATCH_TABLE_H
|
||||
#define BOOST_MSM_BACKMP11_DISPATCH_TABLE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/mp11.hpp>
|
||||
#include <boost/mp11/mpl_list.hpp>
|
||||
#include <boost/mpl/reverse_fold.hpp>
|
||||
#include <boost/mpl/greater.hpp>
|
||||
#include <boost/mpl/filter_view.hpp>
|
||||
#include <boost/mpl/pop_front.hpp>
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <boost/mpl/advance.hpp>
|
||||
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/msm/event_traits.hpp>
|
||||
#include <boost/msm/back/traits.hpp>
|
||||
#include <boost/msm/back/default_compile_policy.hpp>
|
||||
#include <boost/msm/backmp11/metafunctions.hpp>
|
||||
#include <boost/msm/backmp11/common_types.hpp>
|
||||
|
||||
namespace boost { namespace msm { namespace backmp11
|
||||
{
|
||||
|
||||
// Value used to initialize a cell of the dispatch table
|
||||
template<typename Cell>
|
||||
struct init_cell_value
|
||||
{
|
||||
size_t index;
|
||||
Cell address;
|
||||
};
|
||||
template<size_t v1, typename Cell, Cell v2>
|
||||
struct init_cell_constant
|
||||
{
|
||||
static constexpr init_cell_value<Cell> value = {v1, v2};
|
||||
};
|
||||
|
||||
// Type-punned init cell value to suppress redundant template instantiations
|
||||
typedef HandledEnum (*generic_cell)();
|
||||
struct generic_init_cell_value
|
||||
{
|
||||
size_t index;
|
||||
generic_cell address;
|
||||
};
|
||||
|
||||
// Helper to create an array of init cell values for table initialization
|
||||
template<typename Cell, typename InitCellConstants, std::size_t... I>
|
||||
static const init_cell_value<Cell>* const get_init_cells_impl(mp11::index_sequence<I...>)
|
||||
{
|
||||
static constexpr init_cell_value<Cell> values[] {mp11::mp_at_c<InitCellConstants, I>::value...};
|
||||
return values;
|
||||
}
|
||||
template<typename Cell, typename InitCellConstants>
|
||||
static const generic_init_cell_value* const get_init_cells()
|
||||
{
|
||||
return reinterpret_cast<const generic_init_cell_value*>(
|
||||
get_init_cells_impl<Cell, InitCellConstants>(mp11::make_index_sequence<mp11::mp_size<InitCellConstants>::value>{}));
|
||||
}
|
||||
|
||||
template<typename CompilePolicy>
|
||||
struct cell_initializer;
|
||||
|
||||
template<>
|
||||
struct cell_initializer<favor_runtime_speed>
|
||||
{
|
||||
static void init(generic_cell* entries, const generic_init_cell_value* array, size_t size)
|
||||
{
|
||||
for (size_t i=0; i<size; i++)
|
||||
{
|
||||
const auto& item = array[i];
|
||||
entries[item.index] = item.address;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Fsm, typename State, typename Event>
|
||||
struct table_index
|
||||
{
|
||||
using type = mp11::mp_if<
|
||||
mp11::mp_or<
|
||||
mp11::mp_not<is_same<State, Fsm>>,
|
||||
typename has_state_delayed_event<State, Event>::type
|
||||
>,
|
||||
mp11::mp_size_t<get_state_id<typename create_stt<Fsm>::type, State>::value + 1>,
|
||||
mp11::mp_size_t<0>
|
||||
>;
|
||||
};
|
||||
template<typename Fsm, typename State>
|
||||
struct table_index<Fsm, State, void>
|
||||
{
|
||||
using type = mp11::mp_if<
|
||||
mp11::mp_not<is_same<State, Fsm>>,
|
||||
mp11::mp_size_t<get_state_id<typename create_stt<Fsm>::type, State>::value + 1>,
|
||||
mp11::mp_size_t<0>
|
||||
>;
|
||||
};
|
||||
template<typename Fsm, typename State, typename Event = void>
|
||||
using get_table_index = typename table_index<Fsm, State, Event>::type;
|
||||
|
||||
// Generates a singleton runtime lookup table that maps current state
|
||||
// to a function that makes the SM take its transition on the given
|
||||
// Event type.
|
||||
template<class Fsm, class Stt, class CompilePolicy>
|
||||
class dispatch_table;
|
||||
|
||||
template<class Fsm, class Stt>
|
||||
class dispatch_table<Fsm, Stt, favor_runtime_speed>
|
||||
{
|
||||
public:
|
||||
// Dispatch function for a specific event.
|
||||
template<class Event>
|
||||
using cell = HandledEnum (*)(Fsm&, int,int,Event const&);
|
||||
|
||||
// Dispatch an event.
|
||||
template<class Event>
|
||||
static HandledEnum dispatch(Fsm& fsm, int region_id, int state_id, const Event& event)
|
||||
{
|
||||
return event_dispatch_table<Event>::instance().entries[state_id+1](fsm, region_id, state_id, event);
|
||||
}
|
||||
|
||||
// Dispatch an event to the FSM's internal table.
|
||||
template<class Event>
|
||||
static HandledEnum dispatch_internal(Fsm& fsm, int region_id, int state_id, const Event& event)
|
||||
{
|
||||
return event_dispatch_table<Event>::instance().entries[0](fsm, region_id, state_id, event);
|
||||
}
|
||||
|
||||
private:
|
||||
// Compute the maximum state value in the sm so we know how big
|
||||
// to make the tables
|
||||
typedef typename generate_state_set<Stt>::state_set_mp11 state_set_mp11;
|
||||
BOOST_STATIC_CONSTANT(int, max_state = (mp11::mp_size<state_set_mp11>::value));
|
||||
|
||||
// Dispatch table for a specific event.
|
||||
template<class Event>
|
||||
class event_dispatch_table
|
||||
{
|
||||
public:
|
||||
using cell = cell<Event>;
|
||||
|
||||
// The singleton instance.
|
||||
static const event_dispatch_table& instance() {
|
||||
static event_dispatch_table table;
|
||||
return table;
|
||||
}
|
||||
|
||||
private:
|
||||
// initialize the dispatch table for a given Event and Fsm
|
||||
event_dispatch_table()
|
||||
{
|
||||
// Initialize cells for no transition
|
||||
for (size_t i=0;i<max_state+1; i++)
|
||||
{
|
||||
entries[i] = &Fsm::call_no_transition;
|
||||
}
|
||||
// Initialize cells for defer transition
|
||||
typedef mp11::mp_copy_if<
|
||||
typename generate_state_set<Stt>::state_set_mp11,
|
||||
state_filter_predicate
|
||||
> filtered_states;
|
||||
typedef mp11::mp_transform<
|
||||
preprocess_state,
|
||||
filtered_states
|
||||
> preprocessed_states;
|
||||
cell_initializer::init(
|
||||
reinterpret_cast<generic_cell*>(entries),
|
||||
get_init_cells<cell, preprocessed_states>(),
|
||||
mp11::mp_size<preprocessed_states>::value
|
||||
);
|
||||
|
||||
// build chaining rows for rows coming from the same state and the current event
|
||||
// first we build a map of sequence for every source
|
||||
// in reverse order so that the frow's are handled first (UML priority)
|
||||
typedef mp11::mp_fold<
|
||||
mp11::mp_copy_if<
|
||||
typename to_mp_list<Stt>::type,
|
||||
event_filter_predicate
|
||||
>,
|
||||
mp11::mp_list<>,
|
||||
map_updater
|
||||
> map_of_row_seq;
|
||||
// and then build chaining rows for all source states having more than 1 row
|
||||
typedef mp11::mp_transform<
|
||||
row_chainer,
|
||||
map_of_row_seq
|
||||
> chained_rows;
|
||||
typedef mp11::mp_transform<
|
||||
preprocess_row,
|
||||
chained_rows
|
||||
> chained_and_preprocessed_rows;
|
||||
// Go back and fill in cells for matching transitions.
|
||||
cell_initializer::init(
|
||||
reinterpret_cast<generic_cell*>(entries),
|
||||
get_init_cells<cell, chained_and_preprocessed_rows>(),
|
||||
mp11::mp_size<chained_and_preprocessed_rows>::value
|
||||
);
|
||||
}
|
||||
|
||||
// class used to build a chain (or sequence) of transitions for a given event and start state
|
||||
// (like an UML diamond). Allows transition conflicts.
|
||||
template< typename Seq,typename AnEvent,typename State >
|
||||
struct chain_row
|
||||
{
|
||||
typedef State current_state_type;
|
||||
typedef AnEvent transition_event;
|
||||
|
||||
// helper for building a disable/enable_if-controlled execute function
|
||||
struct execute_helper
|
||||
{
|
||||
template <class Sequence>
|
||||
static
|
||||
HandledEnum
|
||||
execute(Fsm& , int, int, Event const& , ::boost::mpl::true_ const & )
|
||||
{
|
||||
// if at least one guard rejected, this will be ignored, otherwise will generate an error
|
||||
return HANDLED_FALSE;
|
||||
}
|
||||
|
||||
template <class Sequence>
|
||||
static
|
||||
HandledEnum
|
||||
execute(Fsm& fsm, int region_index , int state, Event const& evt,
|
||||
::boost::mpl::false_ const & )
|
||||
{
|
||||
// try the first guard
|
||||
typedef typename ::boost::mpl::front<Sequence>::type first_row;
|
||||
HandledEnum res = first_row::execute(fsm,region_index,state,evt);
|
||||
if (HANDLED_TRUE!=res && HANDLED_DEFERRED!=res)
|
||||
{
|
||||
// if the first rejected, move on to the next one
|
||||
HandledEnum sub_res =
|
||||
execute<typename ::boost::mpl::pop_front<Sequence>::type>(fsm,region_index,state,evt,
|
||||
::boost::mpl::bool_<
|
||||
::boost::mpl::empty<typename ::boost::mpl::pop_front<Sequence>::type>::type::value>());
|
||||
// if at least one guards rejects, the event will not generate a call to no_transition
|
||||
if ((HANDLED_FALSE==sub_res) && (HANDLED_GUARD_REJECT==res) )
|
||||
return HANDLED_GUARD_REJECT;
|
||||
else
|
||||
return sub_res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
// Take the transition action and return the next state.
|
||||
static HandledEnum execute(Fsm& fsm, int region_index, int state, Event const& evt)
|
||||
{
|
||||
// forward to helper
|
||||
return execute_helper::template execute<Seq>(fsm,region_index,state,evt,
|
||||
::boost::mpl::bool_< ::boost::mpl::empty<Seq>::type::value>());
|
||||
}
|
||||
};
|
||||
// nullary metafunction whose only job is to prevent early evaluation of _1
|
||||
template< typename Entry >
|
||||
struct make_chain_row_from_map_entry
|
||||
{
|
||||
// if we have more than one frow with the same state as source, remove the ones extra
|
||||
// note: we know the frow's are located at the beginning so we remove at the beginning (number of frows - 1) elements
|
||||
enum { number_frows = boost::mp11::mp_count_if<typename Entry::second, has_is_frow>::value };
|
||||
|
||||
//erases the first NumberToDelete rows
|
||||
template<class Sequence, int NumberToDelete>
|
||||
struct erase_first_rows
|
||||
{
|
||||
typedef typename ::boost::mpl::erase<
|
||||
typename Entry::second,
|
||||
typename ::boost::mpl::begin<Sequence>::type,
|
||||
typename ::boost::mpl::advance<
|
||||
typename ::boost::mpl::begin<Sequence>::type,
|
||||
::boost::mpl::int_<NumberToDelete> >::type
|
||||
>::type type;
|
||||
};
|
||||
// if we have more than 1 frow with this event (not allowed), delete the spare
|
||||
typedef typename ::boost::mpl::eval_if<
|
||||
typename ::boost::mpl::bool_< number_frows >= 2 >::type,
|
||||
erase_first_rows<typename Entry::second,number_frows-1>,
|
||||
::boost::mpl::identity<typename Entry::second>
|
||||
>::type filtered_stt;
|
||||
|
||||
typedef chain_row<filtered_stt,Event,
|
||||
typename Entry::first > type;
|
||||
};
|
||||
// helper for lazy evaluation in eval_if of change_frow_event
|
||||
template <class Transition,class NewEvent>
|
||||
struct replace_event
|
||||
{
|
||||
typedef typename Transition::template replace_event<NewEvent>::type type;
|
||||
};
|
||||
// changes the event type for a frow to the event we are dispatching
|
||||
// this helps ensure that an event does not get processed more than once because of frows and base events.
|
||||
template <class FrowTransition>
|
||||
struct change_frow_event
|
||||
{
|
||||
typedef typename ::boost::mp11::mp_if_c<
|
||||
has_is_frow<FrowTransition>::type::value,
|
||||
replace_event<FrowTransition,Event>,
|
||||
boost::mp11::mp_identity<FrowTransition>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class Transition>
|
||||
struct convert_event_and_forward
|
||||
{
|
||||
static HandledEnum execute(Fsm& fsm, int region_index, int state, Event const& evt)
|
||||
{
|
||||
typename Transition::transition_event forwarded(evt);
|
||||
return Transition::execute(fsm,region_index,state,forwarded);
|
||||
}
|
||||
};
|
||||
|
||||
using init_cell_value = init_cell_value<cell>;
|
||||
|
||||
template<size_t v1, cell v2>
|
||||
using init_cell_constant = init_cell_constant<v1, cell, v2>;
|
||||
|
||||
template<cell v>
|
||||
using cell_constant = std::integral_constant<cell, v>;
|
||||
|
||||
using cell_initializer = cell_initializer<favor_runtime_speed>;
|
||||
|
||||
// Helpers for state processing
|
||||
template<typename State>
|
||||
using state_filter_predicate = typename has_state_delayed_event<State, Event>::type;
|
||||
template<typename State, typename fsm=Fsm>
|
||||
using preprocess_state = init_cell_constant<get_table_index<Fsm, State, Event>::value, &fsm::defer_transition>;
|
||||
|
||||
// Helpers for row processing
|
||||
// First operation (fold)
|
||||
template <typename T>
|
||||
using event_filter_predicate = mp11::mp_and<
|
||||
mp11::mp_not<has_not_real_row_tag<T>>,
|
||||
mp11::mp_or<
|
||||
is_base_of<typename T::transition_event, Event>,
|
||||
typename is_kleene_event<typename T::transition_event>::type
|
||||
>
|
||||
>;
|
||||
template <typename M, typename Key, typename Value>
|
||||
using push_map_value = mp11::mp_push_front<
|
||||
mp11::mp_second<mp11::mp_map_find<M, Key>>,
|
||||
Value>;
|
||||
template<typename M, typename T>
|
||||
using map_updater = mp11::mp_map_replace<
|
||||
M,
|
||||
mp11::mp_list<
|
||||
typename T::current_state_type,
|
||||
mp11::mp_eval_if_c<
|
||||
!mp11::mp_map_contains<M, typename T::current_state_type>::value,
|
||||
// first row on this source state, make a list with 1 element
|
||||
mp11::mp_list<typename change_frow_event<T>::type>,
|
||||
// list already exists, add the row
|
||||
push_map_value,
|
||||
M,
|
||||
typename T::current_state_type,
|
||||
typename change_frow_event<T>::type
|
||||
>
|
||||
>
|
||||
>;
|
||||
// Second operation (transform)
|
||||
template<typename T>
|
||||
using to_mpl_map_entry = mpl::pair<
|
||||
mp11::mp_first<T>,
|
||||
mp11::mp_second<T>
|
||||
>;
|
||||
template<typename T>
|
||||
using row_chainer = mp11::mp_if_c<
|
||||
(mp11::mp_size<typename to_mp_list<mp11::mp_second<T>>::type>::value > 1),
|
||||
// we need row chaining
|
||||
typename make_chain_row_from_map_entry<to_mpl_map_entry<T>>::type,
|
||||
// just one row, no chaining, we rebuild the row like it was before
|
||||
mp11::mp_front<mp11::mp_second<T>>
|
||||
>;
|
||||
template<typename Transition>
|
||||
using preprocess_row_helper = cell_constant<&Transition::execute>;
|
||||
template<typename Transition>
|
||||
using preprocess_row = init_cell_constant<
|
||||
// Offset into the entries array
|
||||
get_table_index<Fsm, typename Transition::current_state_type>::value,
|
||||
// Address of the execute function
|
||||
mp11::mp_eval_if_c<
|
||||
is_kleene_event<typename Transition::transition_event>::type::value,
|
||||
cell_constant<
|
||||
&convert_event_and_forward<Transition>::execute
|
||||
>,
|
||||
preprocess_row_helper,
|
||||
Transition
|
||||
>::value
|
||||
>;
|
||||
|
||||
// data members
|
||||
public:
|
||||
// max_state+1, because 0 is reserved for this fsm (internal transitions)
|
||||
cell entries[max_state+1];
|
||||
};
|
||||
};
|
||||
|
||||
}}} // boost::msm::backmp11
|
||||
|
||||
|
||||
#endif //BOOST_MSM_BACKMP11_DISPATCH_TABLE_H
|
||||
|
||||
328
include/boost/msm/backmp11/favor_compile_time.hpp
Normal file
328
include/boost/msm/backmp11/favor_compile_time.hpp
Normal file
@@ -0,0 +1,328 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_MSM_BACKMP11_FAVOR_COMPILE_TIME_H
|
||||
#define BOOST_MSM_BACKMP11_FAVOR_COMPILE_TIME_H
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#include <any>
|
||||
#endif
|
||||
#include <deque>
|
||||
#include <typeindex>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/mpl/filter_view.hpp>
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
#include <boost/msm/common.hpp>
|
||||
#include <boost/msm/backmp11/metafunctions.hpp>
|
||||
#include <boost/msm/back/common_types.hpp>
|
||||
#include <boost/msm/backmp11/dispatch_table.hpp>
|
||||
|
||||
namespace boost { namespace msm { namespace backmp11
|
||||
{
|
||||
|
||||
#define BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(fsmname) \
|
||||
template<> \
|
||||
const fsmname::sm_dispatch_table& fsmname::sm_dispatch_table::instance() \
|
||||
{ \
|
||||
static dispatch_table table; \
|
||||
return table; \
|
||||
}
|
||||
|
||||
struct favor_compile_time
|
||||
{
|
||||
typedef int compile_policy;
|
||||
typedef ::boost::mpl::false_ add_forwarding_rows;
|
||||
#if __cplusplus >= 201703L
|
||||
typedef std::any any_event;
|
||||
#else
|
||||
typedef boost::any any_event;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class Event>
|
||||
struct is_completion_event<Event, favor_compile_time>
|
||||
{
|
||||
static bool value(const Event& event)
|
||||
{
|
||||
return (event.type() == boost::typeindex::type_id<front::none>());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Stt>
|
||||
struct get_real_rows
|
||||
{
|
||||
template<typename Transition>
|
||||
using is_real_row = mp11::mp_not<typename has_not_real_row_tag<Transition>::type>;
|
||||
typedef mp11::mp_copy_if<Stt, is_real_row> type;
|
||||
};
|
||||
|
||||
// Convert an event to a type index.
|
||||
template<class Event>
|
||||
inline std::type_index to_type_index()
|
||||
{
|
||||
return std::type_index{typeid(Event)};
|
||||
}
|
||||
|
||||
// Helper class to manage end interrupt events.
|
||||
class end_interrupt_event_helper
|
||||
{
|
||||
public:
|
||||
template<class Fsm>
|
||||
end_interrupt_event_helper(const Fsm& fsm)
|
||||
{
|
||||
mp11::mp_for_each<mp11::mp_transform<mp11::mp_identity, typename Fsm::event_set_mp11>>(
|
||||
init_helper<Fsm>{fsm, m_is_flag_active_functions});
|
||||
}
|
||||
|
||||
bool is_end_interrupt_event(const favor_compile_time::any_event& event) const
|
||||
{
|
||||
auto it = m_is_flag_active_functions.find(event.type());
|
||||
if (it != m_is_flag_active_functions.end())
|
||||
{
|
||||
return (it->second)();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
using map = std::unordered_map<std::type_index, std::function<bool()>>;
|
||||
|
||||
template<typename Fsm>
|
||||
class init_helper
|
||||
{
|
||||
public:
|
||||
init_helper(const Fsm& fsm, map& is_flag_active_functions)
|
||||
: m_fsm(fsm), m_is_flag_active_functions(is_flag_active_functions) {}
|
||||
|
||||
template<typename Event>
|
||||
void operator()(mp11::mp_identity<Event>)
|
||||
{
|
||||
using Flag = EndInterruptFlag<Event>;
|
||||
const Fsm* fsm = &m_fsm;
|
||||
m_is_flag_active_functions[to_type_index<Event>()] =
|
||||
[fsm](){return fsm->template is_flag_active<Flag>();};
|
||||
}
|
||||
|
||||
private:
|
||||
const Fsm& m_fsm;
|
||||
map& m_is_flag_active_functions;
|
||||
};
|
||||
|
||||
map m_is_flag_active_functions;
|
||||
};
|
||||
|
||||
struct chain_row
|
||||
{
|
||||
using any_event = favor_compile_time::any_event;
|
||||
|
||||
template<typename Fsm>
|
||||
HandledEnum operator()(Fsm& fsm, int region, int state, any_event const& evt) const
|
||||
{
|
||||
typedef HandledEnum (*real_cell)(Fsm&, int, int, any_event const&);
|
||||
HandledEnum res = HANDLED_FALSE;
|
||||
typename std::deque<generic_cell>::const_iterator it = one_state.begin();
|
||||
while (it != one_state.end() && (res != HANDLED_TRUE && res != HANDLED_DEFERRED ))
|
||||
{
|
||||
auto fnc = reinterpret_cast<real_cell>(reinterpret_cast<void*>(*it));
|
||||
HandledEnum handled = (*fnc)(fsm,region,state,evt);
|
||||
// reject is considered as erasing an error (HANDLED_FALSE)
|
||||
if ((HANDLED_FALSE==handled) && (HANDLED_GUARD_REJECT==res) )
|
||||
res = HANDLED_GUARD_REJECT;
|
||||
else
|
||||
res = handled;
|
||||
++it;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
// Use a deque with a generic type to avoid unnecessary template instantiations.
|
||||
std::deque<generic_cell> one_state;
|
||||
};
|
||||
|
||||
// Generates a singleton runtime lookup table that maps current state
|
||||
// to a function that makes the SM take its transition on the given
|
||||
// Event type.
|
||||
template<class Fsm, class Stt>
|
||||
struct dispatch_table<Fsm, Stt, favor_compile_time>
|
||||
{
|
||||
using any_event = favor_compile_time::any_event;
|
||||
public:
|
||||
// Dispatch an event.
|
||||
static HandledEnum dispatch(Fsm& fsm, int region_id, int state_id, const any_event& event)
|
||||
{
|
||||
return instance().m_state_dispatch_tables[state_id+1].dispatch(fsm, region_id, state_id, event);
|
||||
}
|
||||
|
||||
// Dispatch an event to the FSM's internal table.
|
||||
static HandledEnum dispatch_internal(Fsm& fsm, int region_id, int state_id, const any_event& event)
|
||||
{
|
||||
return instance().m_state_dispatch_tables[0].dispatch(fsm, region_id, state_id, event);
|
||||
}
|
||||
|
||||
private:
|
||||
// Adapter for calling a row's execute function.
|
||||
template<typename Event, typename Row>
|
||||
static HandledEnum convert_and_execute(Fsm& fsm, int region_id, int state_id, const any_event& event)
|
||||
{
|
||||
return Row::execute(fsm, region_id, state_id, *any_cast<Event>(&event));
|
||||
}
|
||||
|
||||
// Dispatch table for one state.
|
||||
class state_dispatch_table
|
||||
{
|
||||
public:
|
||||
// Initialize the table for the given state.
|
||||
template<typename State>
|
||||
void init()
|
||||
{
|
||||
// Fill in cells for deferred events.
|
||||
mp11::mp_for_each<mp11::mp_transform<mp11::mp_identity, to_mp_list_t<typename State::deferred_events>>>(
|
||||
deferred_event_init_helper{m_entries});
|
||||
|
||||
init_call_submachine<State>();
|
||||
}
|
||||
|
||||
template<typename State>
|
||||
typename ::boost::enable_if<is_composite_state<State>, void>::type
|
||||
init_call_submachine()
|
||||
{
|
||||
m_call_submachine = [](Fsm& fsm, const any_event& evt)
|
||||
{
|
||||
return (fsm.template get_state<State&>()).process_event_internal(evt);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename State>
|
||||
typename ::boost::disable_if<is_composite_state<State>, void>::type
|
||||
init_call_submachine()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Event>
|
||||
chain_row& get_chain_row()
|
||||
{
|
||||
return m_entries[to_type_index<Event>()];
|
||||
}
|
||||
|
||||
// Dispatch an event.
|
||||
HandledEnum dispatch(Fsm& fsm, int region_id, int state_id, const any_event& event) const
|
||||
{
|
||||
HandledEnum handled = HANDLED_FALSE;
|
||||
if (m_call_submachine)
|
||||
{
|
||||
handled = m_call_submachine(fsm, event);
|
||||
if (handled)
|
||||
{
|
||||
return handled;
|
||||
}
|
||||
}
|
||||
auto it = m_entries.find(event.type());
|
||||
if (it != m_entries.end())
|
||||
{
|
||||
handled = (it->second)(fsm, region_id, state_id, event);
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
private:
|
||||
class deferred_event_init_helper
|
||||
{
|
||||
public:
|
||||
deferred_event_init_helper(std::unordered_map<std::type_index, chain_row>& entries)
|
||||
: m_entries(entries) {}
|
||||
|
||||
template<typename Event>
|
||||
void operator()(mp11::mp_identity<Event>)
|
||||
{
|
||||
auto& chain_row = m_entries[to_type_index<Event>()];
|
||||
chain_row.one_state.push_front(reinterpret_cast<generic_cell>(&Fsm::template defer_transition<any_event>));
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<std::type_index, chain_row>& m_entries;
|
||||
};
|
||||
|
||||
std::unordered_map<std::type_index, chain_row> m_entries;
|
||||
// Special functor if the state is a composite
|
||||
std::function<HandledEnum(Fsm&, const any_event&)> m_call_submachine;
|
||||
};
|
||||
|
||||
class row_init_helper
|
||||
{
|
||||
public:
|
||||
row_init_helper(state_dispatch_table* state_dispatch_tables)
|
||||
: m_state_dispatch_tables(state_dispatch_tables) {}
|
||||
|
||||
template<typename Row>
|
||||
void operator()(Row)
|
||||
{
|
||||
using Event = typename Row::transition_event;
|
||||
using StateId = get_state_id<Stt, typename Row::current_state_type>;
|
||||
auto& chain_row = m_state_dispatch_tables[StateId::value+1].template get_chain_row<Event>();
|
||||
chain_row.one_state.push_front(reinterpret_cast<generic_cell>(&convert_and_execute<Event, Row>));
|
||||
}
|
||||
|
||||
private:
|
||||
state_dispatch_table* m_state_dispatch_tables;
|
||||
};
|
||||
|
||||
class state_init_helper
|
||||
{
|
||||
public:
|
||||
state_init_helper(state_dispatch_table* state_dispatch_tables)
|
||||
: m_state_dispatch_tables(state_dispatch_tables) {}
|
||||
|
||||
template<typename State>
|
||||
void operator()(mp11::mp_identity<State>)
|
||||
{
|
||||
m_state_dispatch_tables[get_state_id<Stt, State>::value+1].template init<State>();
|
||||
}
|
||||
|
||||
private:
|
||||
state_dispatch_table* m_state_dispatch_tables;
|
||||
};
|
||||
|
||||
// Filter a state to check whether state-specific initialization
|
||||
// needs to be performed.
|
||||
template<typename State>
|
||||
using state_filter_predicate = mp11::mp_or<
|
||||
mp11::mp_not<mp11::mp_empty<to_mp_list_t<typename State::deferred_events>>>,
|
||||
is_composite_state<State>
|
||||
>;
|
||||
|
||||
dispatch_table()
|
||||
{
|
||||
// Execute row-specific initializations.
|
||||
mp11::mp_for_each<typename get_real_rows<Stt>::type>(
|
||||
row_init_helper(m_state_dispatch_tables));
|
||||
|
||||
// Execute state-specific initializations.
|
||||
using filtered_states = mp11::mp_copy_if<state_set_mp11, state_filter_predicate>;
|
||||
mp11::mp_for_each<mp11::mp_transform<mp11::mp_identity, filtered_states>>(
|
||||
state_init_helper(m_state_dispatch_tables));
|
||||
}
|
||||
|
||||
// The singleton instance.
|
||||
static const dispatch_table& instance();
|
||||
|
||||
// Compute the maximum state value in the sm so we know how big
|
||||
// to make the table
|
||||
typedef typename generate_state_set<Stt>::state_set_mp11 state_set_mp11;
|
||||
BOOST_STATIC_CONSTANT(int, max_state = (mp11::mp_size<state_set_mp11>::value));
|
||||
state_dispatch_table m_state_dispatch_tables[max_state+1];
|
||||
};
|
||||
|
||||
}}} // boost::msm::backmp11
|
||||
|
||||
#endif //BOOST_MSM_BACKMP11_FAVOR_COMPILE_TIME_H
|
||||
206
include/boost/msm/backmp11/history_policies.hpp
Normal file
206
include/boost/msm/backmp11/history_policies.hpp
Normal file
@@ -0,0 +1,206 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_MSM_BACKMP11_HISTORY_POLICIES_H
|
||||
#define BOOST_MSM_BACKMP11_HISTORY_POLICIES_H
|
||||
|
||||
#include <boost/msm/backmp11/metafunctions.hpp>
|
||||
|
||||
namespace boost { namespace msm { namespace backmp11
|
||||
{
|
||||
|
||||
// policy classes
|
||||
|
||||
// Default: no history used
|
||||
template <int NumberOfRegions>
|
||||
class NoHistoryImpl
|
||||
{
|
||||
public:
|
||||
NoHistoryImpl(){}
|
||||
~NoHistoryImpl(){}
|
||||
void set_initial_states(int* const initial_states)
|
||||
{
|
||||
for (int i=0;i<NumberOfRegions;++i)
|
||||
m_initialStates[i] = initial_states[i];
|
||||
}
|
||||
void history_exit(int* const )
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
// returns the state where the state machine should be at start
|
||||
template <class Event>
|
||||
const int* history_entry(Event const& )
|
||||
{
|
||||
// always come back to the original state
|
||||
return m_initialStates;
|
||||
}
|
||||
NoHistoryImpl<NumberOfRegions>& operator=(NoHistoryImpl<NumberOfRegions> const& rhs)
|
||||
{
|
||||
for (int i=0; i<NumberOfRegions;++i)
|
||||
{
|
||||
m_initialStates[i] = rhs.m_initialStates[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
// this policy deletes all waiting deferred events
|
||||
template <class Event>
|
||||
bool process_deferred_events(Event const&)const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int)
|
||||
{
|
||||
ar & m_initialStates;
|
||||
}
|
||||
private:
|
||||
int m_initialStates[NumberOfRegions];
|
||||
};
|
||||
|
||||
// not UML standard. Always activates history, no matter which event generated the transition
|
||||
template <int NumberOfRegions>
|
||||
class AlwaysHistoryImpl
|
||||
{
|
||||
public:
|
||||
AlwaysHistoryImpl(){}
|
||||
~AlwaysHistoryImpl(){}
|
||||
void set_initial_states(int* const initial_states)
|
||||
{
|
||||
for (int i=0;i<NumberOfRegions;++i)
|
||||
m_initialStates[i] = initial_states[i];
|
||||
}
|
||||
void history_exit(int* const current_states)
|
||||
{
|
||||
for (int i=0;i<NumberOfRegions;++i)
|
||||
m_initialStates[i] = current_states[i];
|
||||
}
|
||||
// returns the state where the state machine should be at start
|
||||
template <class Event>
|
||||
const int* history_entry(Event const& )
|
||||
{
|
||||
// always load back the last active state
|
||||
return m_initialStates;
|
||||
}
|
||||
AlwaysHistoryImpl<NumberOfRegions>& operator=(AlwaysHistoryImpl<NumberOfRegions> const& rhs)
|
||||
{
|
||||
for (int i=0; i<NumberOfRegions;++i)
|
||||
{
|
||||
m_initialStates[i] = rhs.m_initialStates[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
// the history policy keeps all deferred events until next reentry
|
||||
template <class Event>
|
||||
bool process_deferred_events(Event const&)const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int)
|
||||
{
|
||||
ar & m_initialStates;
|
||||
}
|
||||
private:
|
||||
int m_initialStates[NumberOfRegions];
|
||||
};
|
||||
|
||||
// UML Shallow history. For deep history, just use this policy for all the contained state machines
|
||||
template <class Events,int NumberOfRegions>
|
||||
class ShallowHistoryImpl
|
||||
{
|
||||
typedef typename to_mp_list<Events>::type EventsMp11;
|
||||
|
||||
public:
|
||||
ShallowHistoryImpl(){}
|
||||
~ShallowHistoryImpl(){}
|
||||
void set_initial_states(int* const initial_states)
|
||||
{
|
||||
for (int i=0;i<NumberOfRegions;++i)
|
||||
{
|
||||
m_currentStates[i] = initial_states[i];
|
||||
m_initialStates[i] = initial_states[i];
|
||||
}
|
||||
}
|
||||
void history_exit(int* const current_states)
|
||||
{
|
||||
for (int i=0;i<NumberOfRegions;++i)
|
||||
m_currentStates[i] = current_states[i];
|
||||
}
|
||||
// returns the state where the state machine should be at start
|
||||
template <class Event>
|
||||
const int* history_entry(Event const&)
|
||||
{
|
||||
if (mp11::mp_contains<EventsMp11,Event>::value)
|
||||
{
|
||||
return m_currentStates;
|
||||
}
|
||||
// not one of our events, no history
|
||||
return m_initialStates;
|
||||
}
|
||||
ShallowHistoryImpl<Events,NumberOfRegions>& operator=(ShallowHistoryImpl<Events,NumberOfRegions> const& rhs)
|
||||
{
|
||||
for (int i=0; i<NumberOfRegions;++i)
|
||||
{
|
||||
m_initialStates[i] = rhs.m_initialStates[i];
|
||||
m_currentStates[i] = rhs.m_currentStates[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
// the history policy keeps deferred events until next reentry if coming from our history event
|
||||
template <class Event>
|
||||
bool process_deferred_events(Event const&)const
|
||||
{
|
||||
return mp11::mp_contains<EventsMp11,Event>::value;
|
||||
}
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int)
|
||||
{
|
||||
ar & m_initialStates;
|
||||
ar & m_currentStates;
|
||||
}
|
||||
private:
|
||||
int m_initialStates[NumberOfRegions];
|
||||
int m_currentStates[NumberOfRegions];
|
||||
};
|
||||
|
||||
struct NoHistory
|
||||
{
|
||||
typedef int history_policy;
|
||||
template <int NumberOfRegions>
|
||||
struct apply
|
||||
{
|
||||
typedef NoHistoryImpl<NumberOfRegions> type;
|
||||
};
|
||||
};
|
||||
struct AlwaysHistory
|
||||
{
|
||||
typedef int history_policy;
|
||||
template <int NumberOfRegions>
|
||||
struct apply
|
||||
{
|
||||
typedef AlwaysHistoryImpl<NumberOfRegions> type;
|
||||
};
|
||||
};
|
||||
template <class Events>
|
||||
struct ShallowHistory
|
||||
{
|
||||
typedef int history_policy;
|
||||
template <int NumberOfRegions>
|
||||
struct apply
|
||||
{
|
||||
typedef ShallowHistoryImpl<Events,NumberOfRegions> type;
|
||||
};
|
||||
};
|
||||
|
||||
}}} // boost::msm::backmp11
|
||||
|
||||
#endif //BOOST_MSM_BACKMP11_HISTORY_POLICIES_H
|
||||
951
include/boost/msm/backmp11/metafunctions.hpp
Normal file
951
include/boost/msm/backmp11/metafunctions.hpp
Normal file
@@ -0,0 +1,951 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_MSM_BACKMP11_METAFUNCTIONS_H
|
||||
#define BOOST_MSM_BACKMP11_METAFUNCTIONS_H
|
||||
|
||||
#include "boost/msm/front/completion_event.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/mp11.hpp>
|
||||
#include <boost/mp11/mpl_list.hpp>
|
||||
#include <boost/mpl/set.hpp>
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/mpl/pair.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/mpl/has_xxx.hpp>
|
||||
#include <boost/mpl/find.hpp>
|
||||
#include <boost/mpl/count_if.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/has_key.hpp>
|
||||
#include <boost/mpl/insert.hpp>
|
||||
#include <boost/mpl/next_prior.hpp>
|
||||
#include <boost/mpl/push_back.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/is_sequence.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/mpl/transform.hpp>
|
||||
#include <boost/mpl/begin_end.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/empty.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/mpl/insert_range.hpp>
|
||||
#include <boost/mpl/front.hpp>
|
||||
#include <boost/mpl/logical.hpp>
|
||||
#include <boost/mpl/plus.hpp>
|
||||
#include <boost/mpl/copy_if.hpp>
|
||||
#include <boost/mpl/back_inserter.hpp>
|
||||
#include <boost/mpl/transform.hpp>
|
||||
|
||||
#include <boost/fusion/include/insert_range.hpp>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include <boost/msm/row_tags.hpp>
|
||||
|
||||
// mpl_graph graph implementation and depth first search
|
||||
#include <boost/msm/mpl_graph/incidence_list_graph.hpp>
|
||||
#include <boost/msm/mpl_graph/depth_first_search.hpp>
|
||||
|
||||
#include <boost/msm/back/traits.hpp>
|
||||
#include <boost/msm/back/default_compile_policy.hpp>
|
||||
|
||||
namespace boost { namespace msm { namespace backmp11
|
||||
{
|
||||
|
||||
using back::favor_runtime_speed;
|
||||
|
||||
template <typename Sequence, typename Range>
|
||||
struct set_insert_range
|
||||
{
|
||||
typedef typename ::boost::mpl::fold<
|
||||
Range,Sequence,
|
||||
::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >
|
||||
>::type type;
|
||||
};
|
||||
|
||||
// returns the current state type of a transition
|
||||
template <class Transition>
|
||||
struct transition_source_type
|
||||
{
|
||||
typedef typename Transition::current_state_type type;
|
||||
};
|
||||
|
||||
// returns the target state type of a transition
|
||||
template <class Transition>
|
||||
struct transition_target_type
|
||||
{
|
||||
typedef typename Transition::next_state_type type;
|
||||
};
|
||||
|
||||
// Helper to convert a MPL sequence to Mp11
|
||||
template<typename T>
|
||||
struct to_mp_list
|
||||
{
|
||||
typedef typename mpl::copy<T, mpl::back_inserter<mp11::mp_list<>>>::type type;
|
||||
};
|
||||
template<typename ...T>
|
||||
struct to_mp_list<mp11::mp_list<T...>>
|
||||
{
|
||||
typedef mp11::mp_list<T...> type;
|
||||
};
|
||||
template<typename ...T>
|
||||
using to_mp_list_t = typename to_mp_list<T...>::type;
|
||||
|
||||
template <class stt>
|
||||
struct generate_state_set;
|
||||
|
||||
template <class Fsm>
|
||||
struct get_active_state_switch_policy_helper
|
||||
{
|
||||
typedef typename Fsm::active_state_switch_policy type;
|
||||
};
|
||||
template <class Iter>
|
||||
struct get_active_state_switch_policy_helper2
|
||||
{
|
||||
typedef typename boost::mpl::deref<Iter>::type Fsm;
|
||||
typedef typename Fsm::active_state_switch_policy type;
|
||||
};
|
||||
// returns the active state switching policy
|
||||
template <class Fsm>
|
||||
struct get_active_state_switch_policy
|
||||
{
|
||||
typedef typename ::boost::mpl::find_if<
|
||||
typename Fsm::configuration,
|
||||
has_active_state_switch_policy< ::boost::mpl::placeholders::_1 > >::type iter;
|
||||
|
||||
typedef typename ::boost::mpl::eval_if<
|
||||
typename ::boost::is_same<
|
||||
iter,
|
||||
typename ::boost::mpl::end<typename Fsm::configuration>::type
|
||||
>::type,
|
||||
get_active_state_switch_policy_helper<Fsm>,
|
||||
get_active_state_switch_policy_helper2< iter >
|
||||
>::type type;
|
||||
};
|
||||
|
||||
// returns a mpl::vector containing the init states of a state machine
|
||||
template <class States>
|
||||
struct get_initial_states
|
||||
{
|
||||
typedef typename ::boost::mpl::if_<
|
||||
::boost::mpl::is_sequence<States>,
|
||||
States,
|
||||
typename ::boost::mpl::push_back< ::boost::mpl::vector0<>,States>::type >::type type;
|
||||
};
|
||||
// returns a mpl::int_ containing the size of a region. If the argument is not a sequence, returns 1
|
||||
template <class region>
|
||||
struct get_number_of_regions
|
||||
{
|
||||
typedef typename mpl::if_<
|
||||
::boost::mpl::is_sequence<region>,
|
||||
::boost::mpl::size<region>,
|
||||
::boost::mpl::int_<1> >::type type;
|
||||
};
|
||||
|
||||
// builds a mpl::vector of initial states
|
||||
//TODO remove duplicate from get_initial_states
|
||||
template <class region>
|
||||
struct get_regions_as_sequence
|
||||
{
|
||||
typedef typename ::boost::mpl::if_<
|
||||
::boost::mpl::is_sequence<region>,
|
||||
region,
|
||||
typename ::boost::mpl::push_back< ::boost::mpl::vector0<>,region>::type >::type type;
|
||||
};
|
||||
|
||||
template <class ToCreateSeq>
|
||||
struct get_explicit_creation_as_sequence
|
||||
{
|
||||
typedef typename ::boost::mpl::if_<
|
||||
::boost::mpl::is_sequence<ToCreateSeq>,
|
||||
ToCreateSeq,
|
||||
typename ::boost::mpl::push_back< ::boost::mpl::vector0<>,ToCreateSeq>::type >::type type;
|
||||
};
|
||||
|
||||
// returns true for composite states
|
||||
template <class State>
|
||||
struct is_composite_state
|
||||
{
|
||||
enum {value = has_composite_tag<State>::type::value};
|
||||
typedef typename has_composite_tag<State>::type type;
|
||||
};
|
||||
|
||||
// iterates through a transition table to generate an ordered state set
|
||||
// first the source states, transition up to down
|
||||
// then the target states, up to down
|
||||
template <class stt>
|
||||
struct generate_state_set
|
||||
{
|
||||
typedef typename to_mp_list<stt>::type stt_mp11;
|
||||
// first add the source states
|
||||
template<typename V, typename T>
|
||||
using set_push_source_state = mp11::mp_set_push_back<
|
||||
V,
|
||||
typename T::current_state_type
|
||||
>;
|
||||
typedef typename mp11::mp_fold<
|
||||
typename to_mp_list<stt>::type,
|
||||
mp11::mp_list<>,
|
||||
set_push_source_state
|
||||
> source_state_set_mp11;
|
||||
// then add the target states
|
||||
template<typename V, typename T>
|
||||
using set_push_target_state = mp11::mp_set_push_back<
|
||||
V,
|
||||
typename T::next_state_type
|
||||
>;
|
||||
typedef typename mp11::mp_fold<
|
||||
stt_mp11,
|
||||
source_state_set_mp11,
|
||||
set_push_target_state
|
||||
> state_set_mp11;
|
||||
};
|
||||
|
||||
// extends a state set to a map with key=state and value=id
|
||||
template <class stt>
|
||||
struct generate_state_map
|
||||
{
|
||||
typedef typename generate_state_set<stt>::state_set_mp11 state_set;
|
||||
typedef mp11::mp_iota<mp11::mp_size<state_set>> indices;
|
||||
typedef mp11::mp_transform_q<
|
||||
mp11::mp_bind<mp11::mp_list, mp11::_1, mp11::_2>,
|
||||
state_set,
|
||||
indices
|
||||
> type;
|
||||
};
|
||||
|
||||
// filters the state set to contain only composite states
|
||||
template <class stt>
|
||||
struct generate_composite_state_set
|
||||
{
|
||||
typedef typename generate_state_set<stt>::state_set_mp11 state_set;
|
||||
template<typename State>
|
||||
using is_composite = typename is_composite_state<State>::type;
|
||||
typedef mp11::mp_copy_if<
|
||||
state_set,
|
||||
is_composite
|
||||
> type;
|
||||
};
|
||||
|
||||
// returns the id of a given state
|
||||
template <class stt,class State>
|
||||
struct get_state_id
|
||||
{
|
||||
typedef mp11::mp_second<mp11::mp_map_find<
|
||||
typename generate_state_map<stt>::type,
|
||||
State
|
||||
>> type;
|
||||
|
||||
static constexpr typename type::value_type value = type::value;
|
||||
};
|
||||
|
||||
// iterates through the transition table and generate a set containing all the events
|
||||
template <class stt>
|
||||
struct generate_event_set
|
||||
{
|
||||
typedef typename to_mp_list<stt>::type stt_mp11;
|
||||
template<typename V, typename T>
|
||||
using event_set_pusher = mp11::mp_set_push_back<
|
||||
V,
|
||||
typename T::transition_event
|
||||
>;
|
||||
typedef mp11::mp_fold<
|
||||
typename to_mp_list<stt>::type,
|
||||
mp11::mp_list<>,
|
||||
event_set_pusher
|
||||
> event_set_mp11;
|
||||
};
|
||||
|
||||
// extends an event set to a map with key=event and value=id
|
||||
template <class stt>
|
||||
struct generate_event_map
|
||||
{
|
||||
typedef typename generate_event_set<stt>::event_set_mp11 event_set;
|
||||
typedef mp11::mp_iota<mp11::mp_size<event_set>> indices;
|
||||
typedef mp11::mp_transform_q<
|
||||
mp11::mp_bind<mp11::mp_list, mp11::_1, mp11::_2>,
|
||||
event_set,
|
||||
indices
|
||||
> type;
|
||||
};
|
||||
|
||||
// returns the id of a given event
|
||||
template <class stt,class Event>
|
||||
struct get_event_id
|
||||
{
|
||||
typedef mp11::mp_second<mp11::mp_map_find<
|
||||
typename generate_event_map<stt>::type,
|
||||
Event
|
||||
>> type;
|
||||
enum {value = type::value};
|
||||
};
|
||||
|
||||
// returns a mpl::bool_<true> if State has Event as deferred event
|
||||
template <class State, class Event>
|
||||
struct has_state_delayed_event
|
||||
{
|
||||
typedef typename mp11::mp_contains<
|
||||
typename to_mp_list<typename State::deferred_events>::type,
|
||||
Event
|
||||
> type;
|
||||
};
|
||||
// returns a mpl::bool_<true> if State has any deferred event
|
||||
template <class State>
|
||||
struct has_state_delayed_events
|
||||
{
|
||||
typedef typename mp11::mp_not<mp11::mp_empty<
|
||||
typename to_mp_list<typename State::deferred_events>::type
|
||||
>> type;
|
||||
};
|
||||
|
||||
// Template used to create dummy entries for initial states not found in the stt.
|
||||
template< typename T1 >
|
||||
struct not_a_row
|
||||
{
|
||||
typedef int not_real_row_tag;
|
||||
struct dummy_event
|
||||
{
|
||||
};
|
||||
typedef T1 current_state_type;
|
||||
typedef T1 next_state_type;
|
||||
typedef dummy_event transition_event;
|
||||
};
|
||||
|
||||
// metafunctions used to find out if a state is entry, exit or something else
|
||||
template <class State>
|
||||
struct is_pseudo_entry
|
||||
{
|
||||
typedef typename ::boost::mpl::if_< typename has_pseudo_entry<State>::type,
|
||||
::boost::mpl::bool_<true>,::boost::mpl::bool_<false>
|
||||
>::type type;
|
||||
};
|
||||
// says if a state is an exit pseudo state
|
||||
template <class State>
|
||||
struct is_pseudo_exit
|
||||
{
|
||||
typedef typename has_pseudo_exit<State>::type type;
|
||||
};
|
||||
// says if a state is an entry pseudo state or an explicit entry
|
||||
template <class State>
|
||||
struct is_direct_entry
|
||||
{
|
||||
typedef typename ::boost::mpl::if_< typename has_explicit_entry_state<State>::type,
|
||||
::boost::mpl::bool_<true>, ::boost::mpl::bool_<false>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
//converts a "fake" (simulated in a state_machine_ description )state into one which will really get created
|
||||
template <class StateType,class CompositeType>
|
||||
struct convert_fake_state
|
||||
{
|
||||
// converts a state (explicit entry) into the state we really are going to create (explicit<>)
|
||||
typedef typename ::boost::mpl::if_<
|
||||
typename is_direct_entry<StateType>::type,
|
||||
typename CompositeType::template direct<StateType>,
|
||||
typename ::boost::mpl::identity<StateType>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class StateType>
|
||||
struct get_explicit_creation
|
||||
{
|
||||
typedef typename StateType::explicit_creation type;
|
||||
};
|
||||
|
||||
template <class StateType>
|
||||
struct get_wrapped_entry
|
||||
{
|
||||
typedef typename StateType::wrapped_entry type;
|
||||
};
|
||||
// used for states created with explicit_creation
|
||||
// if the state is an explicit entry, we reach for the wrapped state
|
||||
// otherwise, this returns the state itself
|
||||
template <class StateType>
|
||||
struct get_wrapped_state
|
||||
{
|
||||
typedef typename ::boost::mpl::eval_if<
|
||||
typename has_wrapped_entry<StateType>::type,
|
||||
get_wrapped_entry<StateType>,
|
||||
::boost::mpl::identity<StateType> >::type type;
|
||||
};
|
||||
|
||||
template <class Derived>
|
||||
struct create_stt
|
||||
{
|
||||
//typedef typename Derived::transition_table stt;
|
||||
typedef typename Derived::real_transition_table Stt;
|
||||
// get the state set
|
||||
typedef typename generate_state_set<Stt>::state_set_mp11 states;
|
||||
// transform the initial region(s) in a sequence
|
||||
typedef typename get_regions_as_sequence<typename Derived::initial_state>::type init_states;
|
||||
// iterate through the initial states and add them in the stt if not already there
|
||||
template<typename V, typename T>
|
||||
using states_pusher = mp11::mp_if_c<
|
||||
mp11::mp_set_contains<states, T>::value,
|
||||
V,
|
||||
mp11::mp_push_back<
|
||||
V,
|
||||
not_a_row<typename get_wrapped_state<T>::type>
|
||||
>
|
||||
>;
|
||||
typedef typename mp11::mp_fold<
|
||||
typename to_mp_list<init_states>::type,
|
||||
typename to_mp_list<Stt>::type,
|
||||
states_pusher
|
||||
> with_init;
|
||||
|
||||
// do the same for states marked as explicitly created
|
||||
typedef typename get_explicit_creation_as_sequence<
|
||||
typename ::boost::mpl::eval_if<
|
||||
typename has_explicit_creation<Derived>::type,
|
||||
get_explicit_creation<Derived>,
|
||||
::boost::mpl::vector0<> >::type
|
||||
>::type fake_explicit_created;
|
||||
|
||||
typedef typename
|
||||
::boost::mpl::transform<
|
||||
fake_explicit_created,convert_fake_state< ::boost::mpl::placeholders::_1,Derived> >::type explicit_created;
|
||||
|
||||
typedef typename mp11::mp_fold<
|
||||
typename to_mp_list<explicit_created>::type,
|
||||
with_init,
|
||||
states_pusher
|
||||
> type;
|
||||
};
|
||||
|
||||
// returns the transition table of a Composite state
|
||||
template <class Composite>
|
||||
struct get_transition_table
|
||||
{
|
||||
typedef typename create_stt<Composite>::type type;
|
||||
};
|
||||
|
||||
// recursively builds an internal table including those of substates, sub-substates etc.
|
||||
// variant for submachines
|
||||
template <class StateType,class IsComposite>
|
||||
struct recursive_get_internal_transition_table
|
||||
{
|
||||
// get the composite's internal table
|
||||
typedef typename StateType::internal_transition_table composite_table;
|
||||
// and for every substate (state of submachine), recursively get the internal transition table
|
||||
typedef typename generate_state_set<typename StateType::stt>::state_set_mp11 composite_states;
|
||||
template<typename V, typename T>
|
||||
using append_recursive_internal_transition_table = mp11::mp_append<
|
||||
V,
|
||||
typename recursive_get_internal_transition_table<T, typename has_composite_tag<T>::type>::type
|
||||
>;
|
||||
typedef typename mp11::mp_fold<
|
||||
composite_states,
|
||||
typename to_mp_list<composite_table>::type,
|
||||
append_recursive_internal_transition_table
|
||||
> type;
|
||||
};
|
||||
// stop iterating on leafs (simple states)
|
||||
template <class StateType>
|
||||
struct recursive_get_internal_transition_table<StateType, ::boost::mpl::false_ >
|
||||
{
|
||||
typedef typename to_mp_list<
|
||||
typename StateType::internal_transition_table
|
||||
>::type type;
|
||||
};
|
||||
// recursively get a transition table for a given composite state.
|
||||
// returns the transition table for this state + the tables of all composite sub states recursively
|
||||
template <class Composite>
|
||||
struct recursive_get_transition_table
|
||||
{
|
||||
// get the transition table of the state if it's a state machine
|
||||
template<typename T>
|
||||
using get_transition_table_mp11 = typename get_transition_table<T>::type;
|
||||
typedef typename mp11::mp_eval_if_c<
|
||||
!has_composite_tag<Composite>::type::value,
|
||||
mp11::mp_list<>,
|
||||
get_transition_table_mp11,
|
||||
Composite
|
||||
> org_table;
|
||||
|
||||
typedef typename generate_state_set<org_table>::state_set_mp11 states;
|
||||
|
||||
// and for every substate, recursively get the transition table if it's a state machine
|
||||
template<typename V, typename T>
|
||||
using append_recursive_transition_table = mp11::mp_append<
|
||||
V,
|
||||
typename recursive_get_transition_table<T>::type
|
||||
>;
|
||||
typedef typename mp11::mp_fold<
|
||||
states,
|
||||
org_table,
|
||||
append_recursive_transition_table> type;
|
||||
};
|
||||
|
||||
// metafunction used to say if a SM has pseudo exit states
|
||||
template <class Derived>
|
||||
struct has_fsm_deferred_events
|
||||
{
|
||||
typedef typename create_stt<Derived>::type Stt;
|
||||
typedef typename generate_state_set<Stt>::state_set_mp11 state_set_mp11;
|
||||
|
||||
template<typename T>
|
||||
using has_activate_deferred_events_mp11 = typename has_activate_deferred_events<T>::type;
|
||||
template<typename T>
|
||||
using has_state_delayed_events_mp11 = typename has_state_delayed_events<T>::type;
|
||||
typedef typename mp11::mp_or<
|
||||
typename has_activate_deferred_events<Derived>::type,
|
||||
mp11::mp_any_of<
|
||||
typename to_mp_list<typename Derived::configuration>::type,
|
||||
has_activate_deferred_events_mp11
|
||||
>,
|
||||
mp11::mp_any_of<
|
||||
state_set_mp11,
|
||||
has_state_delayed_events_mp11
|
||||
>
|
||||
> type;
|
||||
};
|
||||
|
||||
struct favor_compile_time;
|
||||
|
||||
// returns a mpl::bool_<true> if State has any delayed event
|
||||
template <class Event, class CompilePolicy>
|
||||
struct is_completion_event;
|
||||
template <class Event>
|
||||
struct is_completion_event<Event, favor_runtime_speed>
|
||||
{
|
||||
typedef typename ::boost::mpl::if_<
|
||||
has_completion_event<Event>,
|
||||
::boost::mpl::bool_<true>,
|
||||
::boost::mpl::bool_<false> >::type type;
|
||||
|
||||
static constexpr bool value(const Event&)
|
||||
{
|
||||
return type::value;
|
||||
}
|
||||
};
|
||||
|
||||
// metafunction used to say if a SM has eventless transitions
|
||||
template <class Derived>
|
||||
struct has_fsm_eventless_transition
|
||||
{
|
||||
typedef typename create_stt<Derived>::type Stt;
|
||||
typedef typename generate_event_set<Stt>::event_set_mp11 event_list;
|
||||
|
||||
typedef mp11::mp_any_of<event_list, has_completion_event> type;
|
||||
};
|
||||
template <class Derived>
|
||||
struct find_completion_events
|
||||
{
|
||||
typedef typename create_stt<Derived>::type Stt;
|
||||
typedef typename generate_event_set<Stt>::event_set_mp11 event_list;
|
||||
|
||||
template<typename T>
|
||||
using has_completion_event_mp11 = typename has_completion_event<T>::type;
|
||||
typedef typename mp11::mp_copy_if<
|
||||
event_list,
|
||||
has_completion_event_mp11
|
||||
> type;
|
||||
};
|
||||
|
||||
template <class Transition>
|
||||
struct make_vector
|
||||
{
|
||||
typedef ::boost::mpl::vector<Transition> type;
|
||||
};
|
||||
template< typename Entry >
|
||||
struct get_first_element_pair_second
|
||||
{
|
||||
typedef typename ::boost::mpl::front<typename Entry::second>::type type;
|
||||
};
|
||||
|
||||
//returns the owner of an explicit_entry state
|
||||
//which is the containing SM if the transition originates from outside the containing SM
|
||||
//or else the explicit_entry state itself
|
||||
template <class State,class ContainingSM>
|
||||
struct get_owner
|
||||
{
|
||||
typedef typename ::boost::mpl::if_<
|
||||
typename ::boost::mpl::not_<typename ::boost::is_same<typename State::owner,
|
||||
ContainingSM >::type>::type,
|
||||
typename State::owner,
|
||||
State >::type type;
|
||||
};
|
||||
|
||||
template <class Sequence,class ContainingSM>
|
||||
struct get_fork_owner
|
||||
{
|
||||
typedef typename ::boost::mpl::front<Sequence>::type seq_front;
|
||||
typedef typename ::boost::mpl::if_<
|
||||
typename ::boost::mpl::not_<
|
||||
typename ::boost::is_same<typename seq_front::owner,ContainingSM>::type>::type,
|
||||
typename seq_front::owner,
|
||||
seq_front >::type type;
|
||||
};
|
||||
|
||||
template <class StateType,class ContainingSM>
|
||||
struct make_exit
|
||||
{
|
||||
typedef typename ::boost::mpl::if_<
|
||||
typename is_pseudo_exit<StateType>::type ,
|
||||
typename ContainingSM::template exit_pt<StateType>,
|
||||
typename ::boost::mpl::identity<StateType>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class StateType,class ContainingSM>
|
||||
struct make_entry
|
||||
{
|
||||
typedef typename ::boost::mpl::if_<
|
||||
typename is_pseudo_entry<StateType>::type ,
|
||||
typename ContainingSM::template entry_pt<StateType>,
|
||||
typename ::boost::mpl::if_<
|
||||
typename is_direct_entry<StateType>::type,
|
||||
typename ContainingSM::template direct<StateType>,
|
||||
typename ::boost::mpl::identity<StateType>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
// metafunction used to say if a SM has pseudo exit states
|
||||
template <class StateType>
|
||||
struct has_exit_pseudo_states_helper
|
||||
{
|
||||
typedef typename StateType::stt Stt;
|
||||
typedef typename generate_state_set<Stt>::type state_list;
|
||||
|
||||
typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
|
||||
state_list,is_pseudo_exit< ::boost::mpl::placeholders::_1> >::value != 0> type;
|
||||
};
|
||||
template <class StateType>
|
||||
struct has_exit_pseudo_states
|
||||
{
|
||||
typedef typename ::boost::mpl::eval_if<typename is_composite_state<StateType>::type,
|
||||
has_exit_pseudo_states_helper<StateType>,
|
||||
::boost::mpl::bool_<false> >::type type;
|
||||
};
|
||||
|
||||
// builds flags (add internal_flag_list and flag_list). internal_flag_list is used for terminate/interrupt states
|
||||
template <class StateType>
|
||||
struct get_flag_list
|
||||
{
|
||||
typedef typename mp11::mp_append<
|
||||
typename to_mp_list<typename StateType::flag_list>::type,
|
||||
typename to_mp_list<typename StateType::internal_flag_list>::type
|
||||
> type;
|
||||
};
|
||||
|
||||
template <class StateType>
|
||||
struct is_state_blocking
|
||||
{
|
||||
template<typename T>
|
||||
using has_event_blocking_flag_mp11 = typename has_event_blocking_flag<T>::type;
|
||||
typedef typename mp11::mp_any_of<
|
||||
typename get_flag_list<StateType>::type,
|
||||
has_event_blocking_flag_mp11
|
||||
> type;
|
||||
|
||||
};
|
||||
// returns a mpl::bool_<true> if fsm has an event blocking flag in one of its substates
|
||||
template <class StateType>
|
||||
struct has_fsm_blocking_states
|
||||
{
|
||||
typedef typename create_stt<StateType>::type Stt;
|
||||
typedef typename generate_state_set<Stt>::state_set_mp11 state_set_mp11;
|
||||
|
||||
template<typename T>
|
||||
using is_state_blocking_mp11 = typename is_state_blocking<T>::type;
|
||||
typedef typename mp11::mp_any_of<
|
||||
state_set_mp11,
|
||||
is_state_blocking_mp11
|
||||
> type;
|
||||
};
|
||||
|
||||
template <class StateType>
|
||||
struct is_no_exception_thrown
|
||||
{
|
||||
typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
|
||||
typename StateType::configuration,
|
||||
has_no_exception_thrown< ::boost::mpl::placeholders::_1 > >::value != 0> found;
|
||||
|
||||
typedef typename ::boost::mpl::or_<
|
||||
typename has_no_exception_thrown<StateType>::type,
|
||||
found
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class StateType>
|
||||
struct is_no_message_queue
|
||||
{
|
||||
typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
|
||||
typename StateType::configuration,
|
||||
has_no_message_queue< ::boost::mpl::placeholders::_1 > >::value != 0> found;
|
||||
|
||||
typedef typename ::boost::mpl::or_<
|
||||
typename has_no_message_queue<StateType>::type,
|
||||
found
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class StateType>
|
||||
struct is_active_state_switch_policy
|
||||
{
|
||||
typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
|
||||
typename StateType::configuration,
|
||||
has_active_state_switch_policy< ::boost::mpl::placeholders::_1 > >::value != 0> found;
|
||||
|
||||
typedef typename ::boost::mpl::or_<
|
||||
typename has_active_state_switch_policy<StateType>::type,
|
||||
found
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class StateType>
|
||||
struct get_initial_event
|
||||
{
|
||||
typedef typename StateType::initial_event type;
|
||||
};
|
||||
|
||||
template <class StateType>
|
||||
struct get_final_event
|
||||
{
|
||||
typedef typename StateType::final_event type;
|
||||
};
|
||||
|
||||
template <class TransitionTable, class InitState>
|
||||
struct build_one_orthogonal_region
|
||||
{
|
||||
template<typename Row>
|
||||
struct row_to_incidence :
|
||||
mp11::mp_list<
|
||||
::boost::mpl::pair<
|
||||
typename Row::next_state_type,
|
||||
typename Row::transition_event>,
|
||||
typename Row::current_state_type,
|
||||
typename Row::next_state_type
|
||||
> {};
|
||||
|
||||
typedef typename mp11::mp_transform<
|
||||
row_to_incidence,
|
||||
typename to_mp_list<TransitionTable>::type
|
||||
> transition_incidence_list;
|
||||
|
||||
typedef ::boost::msm::mpl_graph::incidence_list_graph<transition_incidence_list>
|
||||
transition_graph;
|
||||
|
||||
struct preordering_dfs_visitor :
|
||||
::boost::msm::mpl_graph::dfs_default_visitor_operations
|
||||
{
|
||||
template<typename Node, typename Graph, typename State>
|
||||
struct discover_vertex :
|
||||
::boost::mpl::insert<State, Node>
|
||||
{};
|
||||
};
|
||||
|
||||
typedef typename mpl::first<
|
||||
typename ::boost::msm::mpl_graph::depth_first_search<
|
||||
transition_graph,
|
||||
preordering_dfs_visitor,
|
||||
::boost::mpl::set<>,
|
||||
InitState
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class Fsm>
|
||||
struct find_entry_states
|
||||
{
|
||||
typedef mp11::mp_copy_if<
|
||||
typename Fsm::substate_list,
|
||||
has_explicit_entry_state
|
||||
> type;
|
||||
};
|
||||
|
||||
template <class Set1, class Set2>
|
||||
struct is_common_element
|
||||
{
|
||||
typedef typename ::boost::mpl::fold<
|
||||
Set1, ::boost::mpl::false_,
|
||||
::boost::mpl::if_<
|
||||
::boost::mpl::has_key<
|
||||
Set2,
|
||||
::boost::mpl::placeholders::_2
|
||||
>,
|
||||
::boost::mpl::true_,
|
||||
::boost::mpl::placeholders::_1
|
||||
>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class EntryRegion, class AllRegions>
|
||||
struct add_entry_region
|
||||
{
|
||||
typedef typename ::boost::mpl::transform<
|
||||
AllRegions,
|
||||
::boost::mpl::if_<
|
||||
is_common_element<EntryRegion, ::boost::mpl::placeholders::_1>,
|
||||
set_insert_range< ::boost::mpl::placeholders::_1, EntryRegion>,
|
||||
::boost::mpl::placeholders::_1
|
||||
>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
// build a vector of regions states (as a set)
|
||||
// one set of states for every region
|
||||
template <class Fsm, class InitStates>
|
||||
struct build_orthogonal_regions
|
||||
{
|
||||
typedef typename
|
||||
::boost::mpl::fold<
|
||||
InitStates, ::boost::mpl::vector0<>,
|
||||
::boost::mpl::push_back<
|
||||
::boost::mpl::placeholders::_1,
|
||||
build_one_orthogonal_region< typename Fsm::stt, ::boost::mpl::placeholders::_2 > >
|
||||
>::type without_entries;
|
||||
|
||||
typedef typename
|
||||
::boost::mpl::fold<
|
||||
typename find_entry_states<Fsm>::type, ::boost::mpl::vector0<>,
|
||||
::boost::mpl::push_back<
|
||||
::boost::mpl::placeholders::_1,
|
||||
build_one_orthogonal_region< typename Fsm::stt, ::boost::mpl::placeholders::_2 > >
|
||||
>::type only_entries;
|
||||
|
||||
typedef typename ::boost::mpl::fold<
|
||||
only_entries , without_entries,
|
||||
add_entry_region< ::boost::mpl::placeholders::_2, ::boost::mpl::placeholders::_1>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class GraphAsSeqOfSets, class StateType>
|
||||
struct find_region_index
|
||||
{
|
||||
typedef typename
|
||||
::boost::mpl::fold<
|
||||
GraphAsSeqOfSets, ::boost::mpl::pair< ::boost::mpl::int_< -1 > /*res*/, ::boost::mpl::int_<0> /*counter*/ >,
|
||||
::boost::mpl::if_<
|
||||
::boost::mpl::has_key< ::boost::mpl::placeholders::_2, StateType >,
|
||||
::boost::mpl::pair<
|
||||
::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
|
||||
::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
|
||||
>,
|
||||
::boost::mpl::pair<
|
||||
::boost::mpl::first< ::boost::mpl::placeholders::_1 >,
|
||||
::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
|
||||
>
|
||||
>
|
||||
>::type result_pair;
|
||||
typedef typename ::boost::mpl::first<result_pair>::type type;
|
||||
enum {value = type::value};
|
||||
};
|
||||
|
||||
template <class Fsm>
|
||||
struct check_regions_orthogonality
|
||||
{
|
||||
typedef typename build_orthogonal_regions< Fsm,typename Fsm::initial_states>::type regions;
|
||||
|
||||
typedef typename mp11::mp_apply<
|
||||
mp11::mp_plus,
|
||||
mp11::mp_transform<
|
||||
mp11::mp_size,
|
||||
typename to_mp_list<regions>::type
|
||||
>
|
||||
> number_of_states_in_regions;
|
||||
|
||||
typedef typename ::boost::mpl::fold<
|
||||
regions,mpl::set0<>,
|
||||
set_insert_range<
|
||||
::boost::mpl::placeholders::_1,
|
||||
::boost::mpl::placeholders::_2 >
|
||||
>::type one_big_states_set;
|
||||
|
||||
enum {states_in_regions_raw = number_of_states_in_regions::value};
|
||||
enum {cumulated_states_in_regions_raw = ::boost::mpl::size<one_big_states_set>::value};
|
||||
};
|
||||
|
||||
template <class Fsm>
|
||||
struct check_no_unreachable_state
|
||||
{
|
||||
typedef typename check_regions_orthogonality<Fsm>::one_big_states_set states_in_regions;
|
||||
|
||||
typedef typename set_insert_range<
|
||||
states_in_regions,
|
||||
typename ::boost::mpl::eval_if<
|
||||
typename has_explicit_creation<Fsm>::type,
|
||||
get_explicit_creation<Fsm>,
|
||||
::boost::mpl::vector0<>
|
||||
>::type
|
||||
>::type with_explicit_creation;
|
||||
|
||||
enum {states_in_fsm = ::boost::mpl::size< typename Fsm::substate_list >::value};
|
||||
enum {cumulated_states_in_regions = ::boost::mpl::size< with_explicit_creation >::value};
|
||||
};
|
||||
|
||||
// helper to find out if a SM has an active exit state and is therefore waiting for exiting
|
||||
template <class StateType,class OwnerFct,class FSM>
|
||||
inline
|
||||
typename ::boost::enable_if<typename ::boost::mpl::and_<typename is_composite_state<FSM>::type,
|
||||
typename is_pseudo_exit<StateType>::type>,bool >::type
|
||||
is_exit_state_active(FSM& fsm)
|
||||
{
|
||||
typedef typename OwnerFct::type Composite;
|
||||
//typedef typename create_stt<Composite>::type stt;
|
||||
typedef typename Composite::stt stt;
|
||||
int state_id = get_state_id<stt,StateType>::type::value;
|
||||
Composite& comp = fsm.template get_state<Composite&>();
|
||||
return (std::find(comp.current_state(),comp.current_state()+Composite::nr_regions::value,state_id)
|
||||
!=comp.current_state()+Composite::nr_regions::value);
|
||||
}
|
||||
template <class StateType,class OwnerFct,class FSM>
|
||||
inline
|
||||
typename ::boost::disable_if<typename ::boost::mpl::and_<typename is_composite_state<FSM>::type,
|
||||
typename is_pseudo_exit<StateType>::type>,bool >::type
|
||||
is_exit_state_active(FSM&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// transformation metafunction to end interrupt flags
|
||||
template <class Event>
|
||||
struct transform_to_end_interrupt
|
||||
{
|
||||
typedef boost::msm::EndInterruptFlag<Event> type;
|
||||
};
|
||||
// transform a sequence of events into another one of EndInterruptFlag<Event>
|
||||
template <class Events>
|
||||
struct apply_end_interrupt_flag
|
||||
{
|
||||
typedef typename
|
||||
::boost::mpl::transform<
|
||||
Events,transform_to_end_interrupt< ::boost::mpl::placeholders::_1> >::type type;
|
||||
};
|
||||
// returns a mpl vector containing all end interrupt events if sequence, otherwise the same event
|
||||
template <class Event>
|
||||
struct get_interrupt_events
|
||||
{
|
||||
typedef typename ::boost::mpl::eval_if<
|
||||
::boost::mpl::is_sequence<Event>,
|
||||
apply_end_interrupt_flag<Event>,
|
||||
boost::mpl::vector1<boost::msm::EndInterruptFlag<Event> > >::type type;
|
||||
};
|
||||
|
||||
template <class Events>
|
||||
struct build_interrupt_state_flag_list
|
||||
{
|
||||
typedef ::boost::mpl::vector<boost::msm::InterruptedFlag> first_part;
|
||||
typedef typename ::boost::mpl::insert_range<
|
||||
first_part,
|
||||
typename ::boost::mpl::end< first_part >::type,
|
||||
Events
|
||||
>::type type;
|
||||
};
|
||||
|
||||
}}} // boost::msm::backmp11
|
||||
|
||||
#endif // BOOST_MSM_BACKMP11_METAFUNCTIONS_H
|
||||
3012
include/boost/msm/backmp11/state_machine.hpp
Normal file
3012
include/boost/msm/backmp11/state_machine.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,12 @@ struct wrap{};
|
||||
// tag to use in grammars where states are seen (init_<<, states_<<...)
|
||||
struct state_tag{};
|
||||
|
||||
// helper to print types within metafunctions
|
||||
// TODO:
|
||||
// Remove again
|
||||
template <typename... Ts>
|
||||
struct [[deprecated]] print_types {};
|
||||
|
||||
} } // boost::msm
|
||||
#endif //BOOST_MSM_COMMON_H
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <boost/mpl/filter_view.hpp>
|
||||
#include <boost/mpl/transform_view.hpp>
|
||||
#include <boost/mpl/equal.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
@@ -181,3 +181,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<my_machine_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -105,3 +105,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(anonymous_and_guard_test2, MyStateMachine, MyState
|
||||
BOOST_CHECK_MESSAGE(sm.current_state()[0] == 0, "Running should be active");
|
||||
BOOST_CHECK_MESSAGE(sm.current_state()[1] == 3, "Completed should be active");
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<Bug, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -164,3 +164,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<my_machine_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -11,15 +11,28 @@
|
||||
// back-end
|
||||
#include <boost/msm/back/state_machine.hpp>
|
||||
#include <boost/msm/back/favor_compile_time.hpp>
|
||||
#include <boost/msm/backmp11/state_machine.hpp>
|
||||
#include <boost/msm/backmp11/favor_compile_time.hpp>
|
||||
#include <boost/msm/back11/state_machine.hpp>
|
||||
|
||||
template<typename Front>
|
||||
using get_test_machines = boost::mpl::vector<
|
||||
boost::msm::back::state_machine<Front>,
|
||||
boost::msm::back::state_machine<Front, boost::msm::back::favor_compile_time>,
|
||||
boost::msm::backmp11::state_machine<Front>,
|
||||
boost::msm::backmp11::state_machine<Front, boost::msm::backmp11::favor_compile_time>,
|
||||
boost::msm::back11::state_machine<Front>
|
||||
>;
|
||||
|
||||
template <template <template <typename...> class, typename = void> class hierarchical>
|
||||
using get_hierarchical_test_machines = boost::mpl::vector<
|
||||
hierarchical<boost::msm::back::state_machine>,
|
||||
hierarchical<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
|
||||
hierarchical<boost::msm::backmp11::state_machine>,
|
||||
hierarchical<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>,
|
||||
hierarchical<boost::msm::back11::state_machine>
|
||||
>;
|
||||
|
||||
#define BOOST_MSM_TEST_DEFINE_DEPENDENT_TEMPLATES(frontname) \
|
||||
using base = msm::front::state_machine_def<frontname>; \
|
||||
template<typename T1, class Event, typename T2> \
|
||||
@@ -43,11 +56,3 @@ using get_test_machines = boost::mpl::vector<
|
||||
typename T2, \
|
||||
bool (frontname::*guard)(Event const&) \
|
||||
> using g_row = typename base::template g_row<T1, Event, T2, guard>;
|
||||
|
||||
|
||||
|
||||
// template<typename State, typename Fsm>
|
||||
// State& get_state(Fsm&& fsm)
|
||||
// {
|
||||
// return fsm.template get_state<State&>();
|
||||
// }
|
||||
@@ -263,3 +263,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<my_machine_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -1,18 +1,12 @@
|
||||
file(GLOB SOURCES "*.cpp")
|
||||
# TODO:
|
||||
# Fully install boost to test Serialize
|
||||
list(FILTER SOURCES EXCLUDE REGEX "Serialize|BigWithFunctors")
|
||||
# list(FILTER SOURCES INCLUDE REGEX "Anonymous")
|
||||
# list(FILTER SOURCES EXCLUDE REGEX "xyz")
|
||||
# list(FILTER SOURCES INCLUDE REGEX "xyz")
|
||||
|
||||
add_executable(msm_test
|
||||
${SOURCES}
|
||||
# Anonymous.cpp
|
||||
# AnonymousEuml.cpp
|
||||
# AnonymousAndGuard.cpp
|
||||
# BigWithFunctors.cpp
|
||||
# CompositeMachine.cpp
|
||||
# Entries.cpp
|
||||
main.cpp
|
||||
)
|
||||
target_include_directories(msm_test PRIVATE ../include)
|
||||
find_package(boost_serialization)
|
||||
target_link_libraries(msm_test Boost::serialization)
|
||||
target_compile_definitions(msm_test PRIVATE "BOOST_MSM_NONSTANDALONE_TEST")
|
||||
@@ -150,11 +150,7 @@ namespace
|
||||
typedef Back<player_, Policy> player;
|
||||
};
|
||||
|
||||
typedef boost::mpl::vector<
|
||||
hierarchical_state_machine<boost::msm::back::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
|
||||
hierarchical_state_machine<boost::msm::back11::state_machine>
|
||||
> test_machines;
|
||||
typedef get_hierarchical_test_machines<hierarchical_state_machine> test_machines;
|
||||
|
||||
// static char const* const state_names[] = { "Stopped", "Paused", "Open", "Empty", "Playing" };
|
||||
|
||||
@@ -295,3 +291,8 @@ using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost:
|
||||
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::Playing_type;
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
|
||||
using backmp11_0 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::player;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_0);
|
||||
using backmp11_1 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::Playing_type;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_1);
|
||||
@@ -245,11 +245,7 @@ namespace
|
||||
typedef Back<player_, Policy> player;
|
||||
};
|
||||
// Pick a back-end
|
||||
typedef boost::mpl::vector<
|
||||
hierarchical_state_machine<boost::msm::back::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
|
||||
hierarchical_state_machine<boost::msm::back11::state_machine>
|
||||
> test_machines;
|
||||
typedef get_hierarchical_test_machines<hierarchical_state_machine> test_machines;
|
||||
|
||||
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
|
||||
|
||||
@@ -359,3 +355,8 @@ using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost:
|
||||
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player_::Playing;
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
|
||||
using backmp11_0 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::player;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_0);
|
||||
using backmp11_1 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::player_::Playing;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_1);
|
||||
@@ -207,3 +207,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -226,11 +226,8 @@ namespace
|
||||
};
|
||||
typedef Back<Fsm_, Policy> Fsm;
|
||||
};
|
||||
typedef boost::mpl::vector<
|
||||
hierarchical_state_machine<boost::msm::back::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
|
||||
hierarchical_state_machine<boost::msm::back11::state_machine>
|
||||
> test_machines;
|
||||
|
||||
typedef get_hierarchical_test_machines<hierarchical_state_machine> test_machines;
|
||||
// static char const* const state_names[] = { "State1", "SubFsm2","State2" };
|
||||
|
||||
|
||||
@@ -311,3 +308,8 @@ using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost:
|
||||
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::Fsm_::SubFsm2;
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
|
||||
using backmp11_0 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::Fsm;
|
||||
using backmp11_1 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::Fsm_::SubFsm2;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_0);
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_1);
|
||||
@@ -357,3 +357,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -246,12 +246,7 @@ namespace
|
||||
typedef Back<player_, Policy> player;
|
||||
};
|
||||
// Pick a back-end
|
||||
typedef boost::mpl::vector<
|
||||
hierarchical_state_machine<boost::msm::back::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
|
||||
hierarchical_state_machine<boost::msm::back11::state_machine>
|
||||
> test_machines;
|
||||
|
||||
typedef get_hierarchical_test_machines<hierarchical_state_machine> test_machines;
|
||||
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
|
||||
|
||||
|
||||
@@ -370,4 +365,9 @@ namespace
|
||||
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player;
|
||||
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player_::Playing;
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
|
||||
using backmp11_0 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::player;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_0);
|
||||
using backmp11_1 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::player_::Playing;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_1);
|
||||
@@ -103,3 +103,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<Sm1_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -136,3 +136,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
|
||||
@@ -316,11 +316,7 @@ namespace
|
||||
typedef Back<player_, Policy> player;
|
||||
};
|
||||
// Pick a back-end
|
||||
typedef boost::mpl::vector<
|
||||
hierarchical_state_machine<boost::msm::back::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
|
||||
hierarchical_state_machine<boost::msm::back11::state_machine>
|
||||
> test_machines;
|
||||
typedef get_hierarchical_test_machines<hierarchical_state_machine> test_machines;
|
||||
|
||||
//static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused","AllOk","ErrorMode" };
|
||||
|
||||
@@ -503,4 +499,9 @@ namespace
|
||||
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player;
|
||||
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player_::Playing;
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
|
||||
using backmp11_0 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::player;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_0);
|
||||
using backmp11_1 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::player_::Playing;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_1);
|
||||
@@ -323,11 +323,7 @@ namespace
|
||||
typedef Back<player_, Policy> player;
|
||||
};
|
||||
// Pick a back-end
|
||||
typedef boost::mpl::vector<
|
||||
hierarchical_state_machine<boost::msm::back::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
|
||||
hierarchical_state_machine<boost::msm::back11::state_machine>
|
||||
> test_machines;
|
||||
typedef get_hierarchical_test_machines<hierarchical_state_machine> test_machines;
|
||||
|
||||
//static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused","AllOk","ErrorMode" };
|
||||
|
||||
@@ -510,4 +506,9 @@ namespace
|
||||
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player;
|
||||
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player_::Playing;
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
|
||||
using backmp11_0 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::player;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_0);
|
||||
using backmp11_1 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::player_::Playing;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_1);
|
||||
@@ -343,6 +343,7 @@ namespace
|
||||
// Pick a back-end
|
||||
typedef boost::mpl::vector<
|
||||
hierarchical_state_machine<boost::msm::back::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::backmp11::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::back11::state_machine>
|
||||
> test_machines;
|
||||
|
||||
|
||||
@@ -155,7 +155,9 @@ namespace
|
||||
// Pick a back-end
|
||||
typedef boost::mpl::vector<
|
||||
hierarchical_state_machine<boost::msm::back::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>
|
||||
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
|
||||
hierarchical_state_machine<boost::msm::backmp11::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>
|
||||
// TODO:
|
||||
// Investigate reason for test failure in back11.
|
||||
// hierarchical_state_machine<boost::msm::back11::state_machine>
|
||||
@@ -374,4 +376,9 @@ namespace
|
||||
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player;
|
||||
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::Playing_type;
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
|
||||
using backmp11_0 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::player;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_0);
|
||||
using backmp11_1 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::Playing_type;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_1);
|
||||
@@ -185,9 +185,9 @@ namespace boost::msm::front::puml {
|
||||
struct Action<by_name("resume_playback2")>
|
||||
{
|
||||
template <class EVT, class FSM, class SourceState, class TargetState>
|
||||
void operator()(EVT& e, FSM&, SourceState&, TargetState&)
|
||||
void operator()(EVT const& e, FSM&, SourceState&, TargetState&)
|
||||
{
|
||||
++e.cpt_;
|
||||
++(*const_cast<EVT*>(&e)).cpt_;
|
||||
}
|
||||
};
|
||||
template<>
|
||||
@@ -229,9 +229,9 @@ namespace boost::msm::front::puml {
|
||||
struct Action<by_name("TestFct")>
|
||||
{
|
||||
template <class EVT, class FSM, class SourceState, class TargetState>
|
||||
void operator()(EVT& e, FSM& fsm, SourceState&, TargetState&)
|
||||
void operator()(EVT const& e, FSM& fsm, SourceState&, TargetState&)
|
||||
{
|
||||
++e.cpt_;
|
||||
++(*const_cast<EVT*>(&e)).cpt_;
|
||||
++fsm.test_fct_counter;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -308,3 +308,5 @@ namespace
|
||||
// this is to get rid of warning because p is not const
|
||||
// BOOST_CLASS_TRACKING(player, boost::serialization::track_never)
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -213,3 +213,6 @@ namespace
|
||||
// at the risk of a programming error creating duplicate objects.
|
||||
// this is to get rid of warning because p is not const
|
||||
// BOOST_CLASS_TRACKING(player, boost::serialization::track_never)
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
|
||||
@@ -252,11 +252,7 @@ namespace
|
||||
typedef Back<player_, Policy> player;
|
||||
};
|
||||
// Pick a back-end
|
||||
typedef boost::mpl::vector<
|
||||
hierarchical_state_machine<boost::msm::back::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
|
||||
hierarchical_state_machine<boost::msm::back11::state_machine>
|
||||
> test_machines;
|
||||
typedef get_hierarchical_test_machines<hierarchical_state_machine> test_machines;
|
||||
|
||||
// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
|
||||
|
||||
@@ -381,4 +377,9 @@ namespace
|
||||
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player;
|
||||
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::player_::Playing;
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
|
||||
using backmp11_0 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::player;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_0);
|
||||
using backmp11_1 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::player_::Playing;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_1);
|
||||
|
||||
@@ -134,11 +134,7 @@ namespace
|
||||
typedef Back<Fsm_, Policy> Fsm;
|
||||
};
|
||||
// typedef msm::back11::state_machine<Fsm_> Fsm;
|
||||
typedef boost::mpl::vector<
|
||||
hierarchical_state_machine<boost::msm::back::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
|
||||
hierarchical_state_machine<boost::msm::back11::state_machine>
|
||||
> test_machines;
|
||||
typedef get_hierarchical_test_machines<hierarchical_state_machine> test_machines;
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(set_states_test, test_machine, test_machines)
|
||||
@@ -165,4 +161,9 @@ namespace
|
||||
using back0 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::Fsm;
|
||||
using back1 = hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>::SubFsm;
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1);
|
||||
|
||||
using backmp11_0 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::Fsm;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_0);
|
||||
using backmp11_1 = hierarchical_state_machine<boost::msm::backmp11::state_machine, boost::msm::backmp11::favor_compile_time>::SubFsm;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_1);
|
||||
@@ -194,3 +194,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -194,3 +194,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -273,3 +273,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -252,3 +252,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -329,3 +329,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -14,7 +14,7 @@
|
||||
//front-end
|
||||
#include <boost/msm/front/state_machine_def.hpp>
|
||||
#include <boost/msm/front/puml/puml.hpp>
|
||||
#include <PumlCommon.hpp>
|
||||
#include "PumlCommon.hpp"
|
||||
|
||||
#ifndef BOOST_MSM_NONSTANDALONE_TEST
|
||||
#define BOOST_TEST_MODULE simple_internal_with_puml
|
||||
@@ -154,3 +154,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -254,3 +254,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -129,9 +129,9 @@ namespace
|
||||
struct TestFct
|
||||
{
|
||||
template <class EVT,class FSM,class SourceState,class TargetState>
|
||||
void operator()(EVT& e, FSM& fsm,SourceState& ,TargetState& )
|
||||
void operator()(EVT const& e, FSM& fsm,SourceState& ,TargetState& )
|
||||
{
|
||||
++e.cpt_;
|
||||
++(*const_cast<EVT*>(&e)).cpt_;
|
||||
++fsm.test_fct_counter;
|
||||
}
|
||||
};
|
||||
@@ -182,9 +182,9 @@ namespace
|
||||
struct resume_playback
|
||||
{
|
||||
template <class EVT,class FSM,class SourceState,class TargetState>
|
||||
void operator()(EVT& e,FSM& ,SourceState& ,TargetState& )
|
||||
void operator()(EVT const& e,FSM& ,SourceState& ,TargetState& )
|
||||
{
|
||||
++e.cpt_;
|
||||
++(*const_cast<EVT*>(&e)).cpt_;
|
||||
}
|
||||
};
|
||||
struct stop_and_open
|
||||
@@ -363,3 +363,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -14,7 +14,7 @@
|
||||
//front-end
|
||||
#include <boost/msm/front/state_machine_def.hpp>
|
||||
#include <boost/msm/front/puml/puml.hpp>
|
||||
#include <PumlCommon.hpp>
|
||||
#include "PumlCommon.hpp"
|
||||
|
||||
#ifndef BOOST_MSM_NONSTANDALONE_TEST
|
||||
#define BOOST_TEST_MODULE simple_with_puml_test
|
||||
@@ -134,3 +134,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -14,7 +14,7 @@
|
||||
//front-end
|
||||
#include <boost/msm/front/state_machine_def.hpp>
|
||||
#include <boost/msm/front/puml/puml.hpp>
|
||||
#include <PumlCommon.hpp>
|
||||
#include "PumlCommon.hpp"
|
||||
|
||||
#ifndef BOOST_MSM_NONSTANDALONE_TEST
|
||||
#define BOOST_TEST_MODULE string_terminate_puml_test
|
||||
@@ -92,3 +92,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<front_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -171,4 +171,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<my_machine_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -248,12 +248,7 @@ namespace
|
||||
typedef Back<player_, Policy> player;
|
||||
};
|
||||
// Pick a back-end
|
||||
// typedef msm::back::state_machine<player_> player;
|
||||
typedef boost::mpl::vector<
|
||||
hierarchical_state_machine<boost::msm::back::state_machine>,
|
||||
hierarchical_state_machine<boost::msm::back::state_machine, boost::msm::back::favor_compile_time>,
|
||||
hierarchical_state_machine<boost::msm::back11::state_machine>
|
||||
> test_machines;
|
||||
typedef get_hierarchical_test_machines<hierarchical_state_machine> test_machines;
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE( test_constructor, test_machine, test_machines )
|
||||
|
||||
@@ -115,3 +115,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<bistable_switch_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
@@ -193,4 +193,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
|
||||
@@ -154,4 +154,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
|
||||
@@ -157,4 +157,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
|
||||
@@ -167,4 +167,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<player_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
|
||||
@@ -137,4 +137,5 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<MyMachineFrontend, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
|
||||
@@ -149,3 +149,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(transition_skipping_test, top, tops)
|
||||
BOOST_CHECK_MESSAGE(msm.current_state()[0] == 2, "other2 should be active"); //Open
|
||||
|
||||
}
|
||||
|
||||
using backmp11_fsm = boost::msm::backmp11::state_machine<top_, boost::msm::backmp11::favor_compile_time>;
|
||||
BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm);
|
||||
|
||||
2
test/main.cpp
Normal file
2
test/main.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
Reference in New Issue
Block a user