/Src/Dependencies/Boost/boost/msm/back/metafunctions.hpp

http://hadesmem.googlecode.com/ · C++ Header · 906 lines · 753 code · 88 blank · 65 comment · 8 complexity · d00b2408827e47d888d51a6f9afa90f3 MD5 · raw file

  1. // Copyright 2008 Christophe Henry
  2. // henry UNDERSCORE christophe AT hotmail DOT com
  3. // This is an extended version of the state machine available in the boost::mpl library
  4. // Distributed under the same license as the original.
  5. // Copyright for the original version:
  6. // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
  7. // under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_MSM_BACK_METAFUNCTIONS_H
  11. #define BOOST_MSM_BACK_METAFUNCTIONS_H
  12. #include <boost/mpl/set.hpp>
  13. #include <boost/mpl/at.hpp>
  14. #include <boost/mpl/pair.hpp>
  15. #include <boost/mpl/map.hpp>
  16. #include <boost/mpl/int.hpp>
  17. #include <boost/mpl/has_xxx.hpp>
  18. #include <boost/mpl/find.hpp>
  19. #include <boost/mpl/count_if.hpp>
  20. #include <boost/mpl/fold.hpp>
  21. #include <boost/mpl/if.hpp>
  22. #include <boost/mpl/has_key.hpp>
  23. #include <boost/mpl/insert.hpp>
  24. #include <boost/mpl/next_prior.hpp>
  25. #include <boost/mpl/map.hpp>
  26. #include <boost/mpl/push_back.hpp>
  27. #include <boost/mpl/vector.hpp>
  28. #include <boost/mpl/is_sequence.hpp>
  29. #include <boost/mpl/size.hpp>
  30. #include <boost/mpl/transform.hpp>
  31. #include <boost/mpl/begin_end.hpp>
  32. #include <boost/mpl/bool.hpp>
  33. #include <boost/mpl/empty.hpp>
  34. #include <boost/mpl/identity.hpp>
  35. #include <boost/mpl/eval_if.hpp>
  36. #include <boost/mpl/insert_range.hpp>
  37. #include <boost/mpl/front.hpp>
  38. #include <boost/mpl/logical.hpp>
  39. #include <boost/mpl/plus.hpp>
  40. #include <boost/mpl/copy_if.hpp>
  41. #include <boost/mpl/back_inserter.hpp>
  42. #include <boost/mpl/transform.hpp>
  43. #include <boost/type_traits/is_same.hpp>
  44. #include <boost/utility/enable_if.hpp>
  45. // mpl_graph graph implementation and depth first search
  46. #include <boost/msm/mpl_graph/incidence_list_graph.hpp>
  47. #include <boost/msm/mpl_graph/depth_first_search.hpp>
  48. BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_creation)
  49. BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_entry)
  50. BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_exit)
  51. BOOST_MPL_HAS_XXX_TRAIT_DEF(concrete_exit_state)
  52. BOOST_MPL_HAS_XXX_TRAIT_DEF(composite_tag)
  53. BOOST_MPL_HAS_XXX_TRAIT_DEF(not_real_row_tag)
  54. BOOST_MPL_HAS_XXX_TRAIT_DEF(event_blocking_flag)
  55. BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_entry_state)
  56. BOOST_MPL_HAS_XXX_TRAIT_DEF(completion_event)
  57. BOOST_MPL_HAS_XXX_TRAIT_DEF(no_exception_thrown)
  58. BOOST_MPL_HAS_XXX_TRAIT_DEF(no_message_queue)
  59. BOOST_MPL_HAS_XXX_TRAIT_DEF(activate_deferred_events)
  60. BOOST_MPL_HAS_XXX_TRAIT_DEF(wrapped_entry)
  61. BOOST_MPL_HAS_XXX_TRAIT_DEF(active_state_switch_policy)
  62. namespace boost { namespace msm { namespace back
  63. {
  64. template <typename Sequence, typename Range>
  65. struct set_insert_range
  66. {
  67. typedef typename ::boost::mpl::fold<
  68. Range,Sequence,
  69. ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >
  70. >::type type;
  71. };
  72. // returns the current state type of a transition
  73. template <class Transition>
  74. struct transition_source_type
  75. {
  76. typedef typename Transition::current_state_type type;
  77. };
  78. // returns the target state type of a transition
  79. template <class Transition>
  80. struct transition_target_type
  81. {
  82. typedef typename Transition::next_state_type type;
  83. };
  84. // helper functions for generate_state_ids
  85. // create a pair of a state and a passed id for source and target states
  86. template <class Id,class Transition>
  87. struct make_pair_source_state_id
  88. {
  89. typedef typename ::boost::mpl::pair<typename Transition::current_state_type,Id> type;
  90. };
  91. template <class Id,class Transition>
  92. struct make_pair_target_state_id
  93. {
  94. typedef typename ::boost::mpl::pair<typename Transition::next_state_type,Id> type;
  95. };
  96. // iterates through a transition table and automatically generates ids starting at 0
  97. // first the source states, transition up to down
  98. // then the target states, up to down
  99. template <class stt>
  100. struct generate_state_ids
  101. {
  102. typedef typename
  103. ::boost::mpl::fold<
  104. stt,::boost::mpl::pair< ::boost::mpl::map< >, ::boost::mpl::int_<0> >,
  105. ::boost::mpl::pair<
  106. ::boost::mpl::if_<
  107. ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
  108. transition_source_type< ::boost::mpl::placeholders::_2> >,
  109. ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
  110. ::boost::mpl::insert< ::boost::mpl::first<mpl::placeholders::_1>,
  111. make_pair_source_state_id< ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
  112. ::boost::mpl::placeholders::_2> >
  113. >,
  114. ::boost::mpl::if_<
  115. ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
  116. transition_source_type< ::boost::mpl::placeholders::_2> >,
  117. ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
  118. ::boost::mpl::next< ::boost::mpl::second<mpl::placeholders::_1 > >
  119. >
  120. > //pair
  121. >::type source_state_ids;
  122. typedef typename ::boost::mpl::first<source_state_ids>::type source_state_map;
  123. typedef typename ::boost::mpl::second<source_state_ids>::type highest_state_id;
  124. typedef typename
  125. ::boost::mpl::fold<
  126. stt,::boost::mpl::pair<source_state_map,highest_state_id >,
  127. ::boost::mpl::pair<
  128. ::boost::mpl::if_<
  129. ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
  130. transition_target_type< ::boost::mpl::placeholders::_2> >,
  131. ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
  132. ::boost::mpl::insert< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
  133. make_pair_target_state_id< ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
  134. ::boost::mpl::placeholders::_2> >
  135. >,
  136. ::boost::mpl::if_<
  137. ::boost::mpl::has_key< ::boost::mpl::first< ::boost::mpl::placeholders::_1>,
  138. transition_target_type< ::boost::mpl::placeholders::_2> >,
  139. ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
  140. ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
  141. >
  142. > //pair
  143. >::type all_state_ids;
  144. typedef typename ::boost::mpl::first<all_state_ids>::type type;
  145. };
  146. template <class Fsm>
  147. struct get_active_state_switch_policy_helper
  148. {
  149. typedef typename Fsm::active_state_switch_policy type;
  150. };
  151. template <class Iter>
  152. struct get_active_state_switch_policy_helper2
  153. {
  154. typedef typename boost::mpl::deref<Iter>::type Fsm;
  155. typedef typename Fsm::active_state_switch_policy type;
  156. };
  157. // returns the active state switching policy
  158. template <class Fsm>
  159. struct get_active_state_switch_policy
  160. {
  161. typedef typename ::boost::mpl::find_if<
  162. typename Fsm::configuration,
  163. has_active_state_switch_policy< ::boost::mpl::placeholders::_1 > >::type iter;
  164. typedef typename ::boost::mpl::eval_if<
  165. typename ::boost::is_same<
  166. iter,
  167. typename ::boost::mpl::end<typename Fsm::configuration>::type
  168. >::type,
  169. get_active_state_switch_policy_helper<Fsm>,
  170. get_active_state_switch_policy_helper2< iter >
  171. >::type type;
  172. };
  173. // returns the id of a given state
  174. template <class stt,class State>
  175. struct get_state_id
  176. {
  177. typedef typename ::boost::mpl::at<typename generate_state_ids<stt>::type,State>::type type;
  178. enum {value = type::value};
  179. };
  180. // returns a mpl::vector containing the init states of a state machine
  181. template <class States>
  182. struct get_initial_states
  183. {
  184. typedef typename ::boost::mpl::if_<
  185. ::boost::mpl::is_sequence<States>,
  186. States,
  187. typename ::boost::mpl::push_back< ::boost::mpl::vector0<>,States>::type >::type type;
  188. };
  189. // returns a mpl::int_ containing the size of a region. If the argument is not a sequence, returns 1
  190. template <class region>
  191. struct get_number_of_regions
  192. {
  193. typedef typename mpl::if_<
  194. ::boost::mpl::is_sequence<region>,
  195. ::boost::mpl::size<region>,
  196. ::boost::mpl::int_<1> >::type type;
  197. };
  198. // builds a mpl::vector of initial states
  199. //TODO remove duplicate from get_initial_states
  200. template <class region>
  201. struct get_regions_as_sequence
  202. {
  203. typedef typename ::boost::mpl::if_<
  204. ::boost::mpl::is_sequence<region>,
  205. region,
  206. typename ::boost::mpl::push_back< ::boost::mpl::vector0<>,region>::type >::type type;
  207. };
  208. template <class ToCreateSeq>
  209. struct get_explicit_creation_as_sequence
  210. {
  211. typedef typename ::boost::mpl::if_<
  212. ::boost::mpl::is_sequence<ToCreateSeq>,
  213. ToCreateSeq,
  214. typename ::boost::mpl::push_back< ::boost::mpl::vector0<>,ToCreateSeq>::type >::type type;
  215. };
  216. // returns true if 2 transitions have the same source (used to remove duplicates in search of composite states)
  217. template <class stt,class Transition1,class Transition2>
  218. struct have_same_source
  219. {
  220. enum {current_state1 = get_state_id<stt,typename Transition1::current_state_type >::type::value};
  221. enum {current_state2 = get_state_id<stt,typename Transition2::current_state_type >::type::value};
  222. enum {value = ((int)current_state1 == (int)current_state2) };
  223. };
  224. // A metafunction that returns the Event associated with a transition.
  225. template <class Transition>
  226. struct transition_event
  227. {
  228. typedef typename Transition::transition_event type;
  229. };
  230. // returns true for composite states
  231. template <class State>
  232. struct is_composite_state
  233. {
  234. enum {value = has_composite_tag<State>::type::value};
  235. typedef typename has_composite_tag<State>::type type;
  236. };
  237. // transform a transition table in a container of source states
  238. template <class stt>
  239. struct keep_source_names
  240. {
  241. // instead of the rows we want only the names of the states (from source)
  242. typedef typename
  243. ::boost::mpl::transform<
  244. stt,transition_source_type< ::boost::mpl::placeholders::_1> >::type type;
  245. };
  246. // transform a transition table in a container of target states
  247. template <class stt>
  248. struct keep_target_names
  249. {
  250. // instead of the rows we want only the names of the states (from source)
  251. typedef typename
  252. ::boost::mpl::transform<
  253. stt,transition_target_type< ::boost::mpl::placeholders::_1> >::type type;
  254. };
  255. template <class stt>
  256. struct generate_state_set
  257. {
  258. // keep in the original transition table only the source/target state types
  259. typedef typename keep_source_names<stt>::type sources;
  260. typedef typename keep_target_names<stt>::type targets;
  261. typedef typename
  262. ::boost::mpl::fold<
  263. sources, ::boost::mpl::set<>,
  264. ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>
  265. >::type source_set;
  266. typedef typename
  267. ::boost::mpl::fold<
  268. targets,source_set,
  269. ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>
  270. >::type type;
  271. };
  272. // iterates through the transition table and generate a mpl::set<> containing all the events
  273. template <class stt>
  274. struct generate_event_set
  275. {
  276. typedef typename
  277. ::boost::mpl::fold<
  278. stt, ::boost::mpl::set<>,
  279. ::boost::mpl::if_<
  280. ::boost::mpl::has_key< ::boost::mpl::placeholders::_1,
  281. transition_event< ::boost::mpl::placeholders::_2> >,
  282. ::boost::mpl::placeholders::_1,
  283. ::boost::mpl::insert< ::boost::mpl::placeholders::_1,
  284. transition_event< ::boost::mpl::placeholders::_2> > >
  285. >::type type;
  286. };
  287. // returns a mpl::bool_<true> if State has Event as deferred event
  288. template <class State, class Event>
  289. struct has_state_delayed_event
  290. {
  291. typedef typename ::boost::mpl::find<typename State::deferred_events,Event>::type found;
  292. typedef typename ::boost::mpl::if_<
  293. ::boost::is_same<found,typename ::boost::mpl::end<typename State::deferred_events>::type >,
  294. ::boost::mpl::bool_<false>,
  295. ::boost::mpl::bool_<true> >::type type;
  296. };
  297. // returns a mpl::bool_<true> if State has any deferred event
  298. template <class State>
  299. struct has_state_delayed_events
  300. {
  301. typedef typename ::boost::mpl::if_<
  302. ::boost::mpl::empty<typename State::deferred_events>,
  303. ::boost::mpl::bool_<false>,
  304. ::boost::mpl::bool_<true> >::type type;
  305. };
  306. // Template used to create dummy entries for initial states not found in the stt.
  307. template< typename T1 >
  308. struct not_a_row
  309. {
  310. typedef int not_real_row_tag;
  311. struct dummy_event
  312. {
  313. };
  314. typedef T1 current_state_type;
  315. typedef T1 next_state_type;
  316. typedef dummy_event transition_event;
  317. };
  318. // metafunctions used to find out if a state is entry, exit or something else
  319. template <class State>
  320. struct is_pseudo_entry
  321. {
  322. typedef typename ::boost::mpl::if_< typename has_pseudo_entry<State>::type,
  323. ::boost::mpl::bool_<true>,::boost::mpl::bool_<false>
  324. >::type type;
  325. };
  326. // says if a state is an exit pseudo state
  327. template <class State>
  328. struct is_pseudo_exit
  329. {
  330. typedef typename ::boost::mpl::if_< typename has_pseudo_exit<State>::type,
  331. ::boost::mpl::bool_<true>, ::boost::mpl::bool_<false>
  332. >::type type;
  333. };
  334. // says if a state is an entry pseudo state or an explicit entry
  335. template <class State>
  336. struct is_direct_entry
  337. {
  338. typedef typename ::boost::mpl::if_< typename has_explicit_entry_state<State>::type,
  339. ::boost::mpl::bool_<true>, ::boost::mpl::bool_<false>
  340. >::type type;
  341. };
  342. //converts a "fake" (simulated in a state_machine_ description )state into one which will really get created
  343. template <class StateType,class CompositeType>
  344. struct convert_fake_state
  345. {
  346. // converts a state (explicit entry) into the state we really are going to create (explicit<>)
  347. typedef typename ::boost::mpl::if_<
  348. typename is_direct_entry<StateType>::type,
  349. typename CompositeType::template direct<StateType>,
  350. typename ::boost::mpl::identity<StateType>::type
  351. >::type type;
  352. };
  353. template <class StateType>
  354. struct get_explicit_creation
  355. {
  356. typedef typename StateType::explicit_creation type;
  357. };
  358. template <class StateType>
  359. struct get_wrapped_entry
  360. {
  361. typedef typename StateType::wrapped_entry type;
  362. };
  363. // used for states created with explicit_creation
  364. // if the state is an explicit entry, we reach for the wrapped state
  365. // otherwise, this returns the state itself
  366. template <class StateType>
  367. struct get_wrapped_state
  368. {
  369. typedef typename ::boost::mpl::eval_if<
  370. typename has_wrapped_entry<StateType>::type,
  371. get_wrapped_entry<StateType>,
  372. ::boost::mpl::identity<StateType> >::type type;
  373. };
  374. template <class Derived>
  375. struct create_stt
  376. {
  377. //typedef typename Derived::transition_table stt;
  378. typedef typename Derived::real_transition_table Stt;
  379. // get the state set
  380. typedef typename generate_state_set<Stt>::type states;
  381. // transform the initial region(s) in a sequence
  382. typedef typename get_regions_as_sequence<typename Derived::initial_state>::type init_states;
  383. // iterate through the initial states and add them in the stt if not already there
  384. typedef typename
  385. ::boost::mpl::fold<
  386. init_states,Stt,
  387. ::boost::mpl::if_<
  388. ::boost::mpl::has_key<states, ::boost::mpl::placeholders::_2>,
  389. ::boost::mpl::placeholders::_1,
  390. ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::end< ::boost::mpl::placeholders::_1>,
  391. not_a_row< get_wrapped_state< ::boost::mpl::placeholders::_2> > >
  392. >
  393. >::type with_init;
  394. // do the same for states marked as explicitly created
  395. typedef typename get_explicit_creation_as_sequence<
  396. typename ::boost::mpl::eval_if<
  397. typename has_explicit_creation<Derived>::type,
  398. get_explicit_creation<Derived>,
  399. ::boost::mpl::vector0<> >::type
  400. >::type fake_explicit_created;
  401. typedef typename
  402. ::boost::mpl::transform<
  403. fake_explicit_created,convert_fake_state< ::boost::mpl::placeholders::_1,Derived> >::type explicit_created;
  404. typedef typename
  405. ::boost::mpl::fold<
  406. explicit_created,with_init,
  407. ::boost::mpl::if_<
  408. ::boost::mpl::has_key<states, ::boost::mpl::placeholders::_2>,
  409. ::boost::mpl::placeholders::_1,
  410. ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::end<mpl::placeholders::_1>,
  411. not_a_row< get_wrapped_state< ::boost::mpl::placeholders::_2> > >
  412. >
  413. >::type type;
  414. };
  415. // returns the transition table of a Composite state
  416. template <class Composite>
  417. struct get_transition_table
  418. {
  419. typedef typename create_stt<Composite>::type type;
  420. };
  421. // recursively get a transition table for a given composite state.
  422. // returns the transition table for this state + the tables of all composite sub states recursively
  423. template <class Composite>
  424. struct recursive_get_transition_table
  425. {
  426. // get the transition table of the state if it's a state machine
  427. typedef typename ::boost::mpl::eval_if<typename is_composite_state<Composite>::type,
  428. get_transition_table<Composite>,
  429. ::boost::mpl::vector0<> >::type org_table;
  430. typedef typename generate_state_set<org_table>::type states;
  431. // and for every substate, recursively get the transition table if it's a state machine
  432. typedef typename ::boost::mpl::fold<
  433. states,org_table,
  434. ::boost::mpl::insert_range< ::boost::mpl::placeholders::_1, ::boost::mpl::end<mpl::placeholders::_1>,
  435. recursive_get_transition_table< ::boost::mpl::placeholders::_2 > >
  436. >::type type;
  437. };
  438. // metafunction used to say if a SM has pseudo exit states
  439. template <class Derived>
  440. struct has_fsm_deferred_events
  441. {
  442. typedef typename create_stt<Derived>::type Stt;
  443. typedef typename generate_state_set<Stt>::type state_list;
  444. typedef typename ::boost::mpl::or_<
  445. typename has_activate_deferred_events<Derived>::type,
  446. ::boost::mpl::bool_< ::boost::mpl::count_if<
  447. typename Derived::configuration,
  448. has_activate_deferred_events< ::boost::mpl::placeholders::_1 > >::value != 0>
  449. >::type found_in_fsm;
  450. typedef typename ::boost::mpl::or_<
  451. found_in_fsm,
  452. ::boost::mpl::bool_< ::boost::mpl::count_if<
  453. state_list,has_state_delayed_events<
  454. ::boost::mpl::placeholders::_1 > >::value != 0>
  455. >::type type;
  456. };
  457. // returns a mpl::bool_<true> if State has any delayed event
  458. template <class Event>
  459. struct is_completion_event
  460. {
  461. typedef typename ::boost::mpl::if_<
  462. has_completion_event<Event>,
  463. ::boost::mpl::bool_<true>,
  464. ::boost::mpl::bool_<false> >::type type;
  465. };
  466. // metafunction used to say if a SM has eventless transitions
  467. template <class Derived>
  468. struct has_fsm_eventless_transition
  469. {
  470. typedef typename create_stt<Derived>::type Stt;
  471. typedef typename generate_event_set<Stt>::type event_list;
  472. typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
  473. event_list,is_completion_event< ::boost::mpl::placeholders::_1 > >::value != 0> type;
  474. };
  475. template <class Derived>
  476. struct find_completion_events
  477. {
  478. typedef typename create_stt<Derived>::type Stt;
  479. typedef typename generate_event_set<Stt>::type event_list;
  480. typedef typename ::boost::mpl::fold<
  481. event_list, ::boost::mpl::set<>,
  482. ::boost::mpl::if_<
  483. is_completion_event< ::boost::mpl::placeholders::_2>,
  484. ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >,
  485. ::boost::mpl::placeholders::_1 >
  486. >::type type;
  487. };
  488. template <class Transition>
  489. struct make_vector
  490. {
  491. typedef ::boost::mpl::vector<Transition> type;
  492. };
  493. template< typename Entry >
  494. struct get_first_element_pair_second
  495. {
  496. typedef typename ::boost::mpl::front<typename Entry::second>::type type;
  497. };
  498. //returns the owner of an explicit_entry state
  499. //which is the containing SM if the transition originates from outside the containing SM
  500. //or else the explicit_entry state itself
  501. template <class State,class ContainingSM>
  502. struct get_owner
  503. {
  504. typedef typename ::boost::mpl::if_<
  505. typename ::boost::mpl::not_<typename ::boost::is_same<typename State::owner,
  506. ContainingSM >::type>::type,
  507. typename State::owner,
  508. State >::type type;
  509. };
  510. template <class Sequence,class ContainingSM>
  511. struct get_fork_owner
  512. {
  513. typedef typename ::boost::mpl::front<Sequence>::type seq_front;
  514. typedef typename ::boost::mpl::if_<
  515. typename ::boost::mpl::not_<
  516. typename ::boost::is_same<typename seq_front::owner,ContainingSM>::type>::type,
  517. typename seq_front::owner,
  518. seq_front >::type type;
  519. };
  520. template <class StateType,class ContainingSM>
  521. struct make_exit
  522. {
  523. typedef typename ::boost::mpl::if_<
  524. typename is_pseudo_exit<StateType>::type ,
  525. typename ContainingSM::template exit_pt<StateType>,
  526. typename ::boost::mpl::identity<StateType>::type
  527. >::type type;
  528. };
  529. template <class StateType,class ContainingSM>
  530. struct make_entry
  531. {
  532. typedef typename ::boost::mpl::if_<
  533. typename is_pseudo_entry<StateType>::type ,
  534. typename ContainingSM::template entry_pt<StateType>,
  535. typename ::boost::mpl::if_<
  536. typename is_direct_entry<StateType>::type,
  537. typename ContainingSM::template direct<StateType>,
  538. typename ::boost::mpl::identity<StateType>::type
  539. >::type
  540. >::type type;
  541. };
  542. // metafunction used to say if a SM has pseudo exit states
  543. template <class StateType>
  544. struct has_exit_pseudo_states_helper
  545. {
  546. typedef typename StateType::stt Stt;
  547. typedef typename generate_state_set<Stt>::type state_list;
  548. typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
  549. state_list,is_pseudo_exit< ::boost::mpl::placeholders::_1> >::value != 0> type;
  550. };
  551. template <class StateType>
  552. struct has_exit_pseudo_states
  553. {
  554. typedef typename ::boost::mpl::eval_if<typename is_composite_state<StateType>::type,
  555. has_exit_pseudo_states_helper<StateType>,
  556. ::boost::mpl::bool_<false> >::type type;
  557. };
  558. template <class StateType>
  559. struct is_state_blocking
  560. {
  561. typedef typename ::boost::mpl::fold<
  562. typename StateType::flag_list, ::boost::mpl::set<>,
  563. ::boost::mpl::if_<
  564. has_event_blocking_flag< ::boost::mpl::placeholders::_2>,
  565. ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >,
  566. ::boost::mpl::placeholders::_1 >
  567. >::type blocking_flags;
  568. typedef typename ::boost::mpl::if_<
  569. ::boost::mpl::empty<blocking_flags>,
  570. ::boost::mpl::bool_<false>,
  571. ::boost::mpl::bool_<true> >::type type;
  572. };
  573. // returns a mpl::bool_<true> if fsm has an event blocking flag in one of its substates
  574. template <class StateType>
  575. struct has_fsm_blocking_states
  576. {
  577. typedef typename create_stt<StateType>::type Stt;
  578. typedef typename generate_state_set<Stt>::type state_list;
  579. typedef typename ::boost::mpl::fold<
  580. state_list, ::boost::mpl::set<>,
  581. ::boost::mpl::if_<
  582. is_state_blocking< ::boost::mpl::placeholders::_2>,
  583. ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >,
  584. ::boost::mpl::placeholders::_1 >
  585. >::type blocking_states;
  586. typedef typename ::boost::mpl::if_<
  587. ::boost::mpl::empty<blocking_states>,
  588. ::boost::mpl::bool_<false>,
  589. ::boost::mpl::bool_<true> >::type type;
  590. };
  591. template <class StateType>
  592. struct is_no_exception_thrown
  593. {
  594. typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
  595. typename StateType::configuration,
  596. has_no_exception_thrown< ::boost::mpl::placeholders::_1 > >::value != 0> found;
  597. typedef typename ::boost::mpl::or_<
  598. typename has_no_exception_thrown<StateType>::type,
  599. found
  600. >::type type;
  601. };
  602. template <class StateType>
  603. struct is_no_message_queue
  604. {
  605. typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
  606. typename StateType::configuration,
  607. has_no_message_queue< ::boost::mpl::placeholders::_1 > >::value != 0> found;
  608. typedef typename ::boost::mpl::or_<
  609. typename has_no_message_queue<StateType>::type,
  610. found
  611. >::type type;
  612. };
  613. template <class StateType>
  614. struct is_active_state_switch_policy
  615. {
  616. typedef ::boost::mpl::bool_< ::boost::mpl::count_if<
  617. typename StateType::configuration,
  618. has_active_state_switch_policy< ::boost::mpl::placeholders::_1 > >::value != 0> found;
  619. typedef typename ::boost::mpl::or_<
  620. typename has_active_state_switch_policy<StateType>::type,
  621. found
  622. >::type type;
  623. };
  624. template <class StateType>
  625. struct get_initial_event
  626. {
  627. typedef typename StateType::initial_event type;
  628. };
  629. template <class StateType>
  630. struct get_final_event
  631. {
  632. typedef typename StateType::final_event type;
  633. };
  634. template <class TransitionTable, class InitState>
  635. struct build_one_orthogonal_region
  636. {
  637. template<typename Row>
  638. struct row_to_incidence :
  639. ::boost::mpl::vector<
  640. ::boost::mpl::pair<
  641. typename Row::next_state_type,
  642. typename Row::transition_event>,
  643. typename Row::current_state_type,
  644. typename Row::next_state_type
  645. > {};
  646. template <class Seq, class Elt>
  647. struct transition_incidence_list_helper
  648. {
  649. typedef typename ::boost::mpl::push_back< Seq, row_to_incidence< Elt > >::type type;
  650. };
  651. typedef typename ::boost::mpl::fold<
  652. TransitionTable,
  653. ::boost::mpl::vector<>,
  654. transition_incidence_list_helper< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>
  655. >::type transition_incidence_list;
  656. typedef ::boost::msm::mpl_graph::incidence_list_graph<transition_incidence_list>
  657. transition_graph;
  658. struct preordering_dfs_visitor :
  659. ::boost::msm::mpl_graph::dfs_default_visitor_operations
  660. {
  661. template<typename Node, typename Graph, typename State>
  662. struct discover_vertex :
  663. ::boost::mpl::insert<State, Node>
  664. {};
  665. };
  666. typedef typename mpl::first<
  667. typename ::boost::msm::mpl_graph::depth_first_search<
  668. transition_graph,
  669. preordering_dfs_visitor,
  670. ::boost::mpl::set<>,
  671. InitState
  672. >::type
  673. >::type type;
  674. };
  675. template <class Fsm>
  676. struct find_entry_states
  677. {
  678. typedef typename ::boost::mpl::copy<
  679. typename Fsm::substate_list,
  680. ::boost::mpl::inserter<
  681. ::boost::mpl::set0<>,
  682. ::boost::mpl::if_<
  683. has_explicit_entry_state< ::boost::mpl::placeholders::_2 >,
  684. ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>,
  685. ::boost::mpl::placeholders::_1
  686. >
  687. >
  688. >::type type;
  689. };
  690. template <class Set1, class Set2>
  691. struct is_common_element
  692. {
  693. typedef typename ::boost::mpl::fold<
  694. Set1, ::boost::mpl::false_,
  695. ::boost::mpl::if_<
  696. ::boost::mpl::has_key<
  697. Set2,
  698. ::boost::mpl::placeholders::_2
  699. >,
  700. ::boost::mpl::true_,
  701. ::boost::mpl::placeholders::_1
  702. >
  703. >::type type;
  704. };
  705. template <class EntryRegion, class AllRegions>
  706. struct add_entry_region
  707. {
  708. typedef typename ::boost::mpl::transform<
  709. AllRegions,
  710. ::boost::mpl::if_<
  711. is_common_element<EntryRegion, ::boost::mpl::placeholders::_1>,
  712. set_insert_range< ::boost::mpl::placeholders::_1, EntryRegion>,
  713. ::boost::mpl::placeholders::_1
  714. >
  715. >::type type;
  716. };
  717. // build a vector of regions states (as a set)
  718. // one set of states for every region
  719. template <class Fsm, class InitStates>
  720. struct build_orthogonal_regions
  721. {
  722. typedef typename
  723. ::boost::mpl::fold<
  724. InitStates, ::boost::mpl::vector0<>,
  725. ::boost::mpl::push_back<
  726. ::boost::mpl::placeholders::_1,
  727. build_one_orthogonal_region< typename Fsm::stt, ::boost::mpl::placeholders::_2 > >
  728. >::type without_entries;
  729. typedef typename
  730. ::boost::mpl::fold<
  731. typename find_entry_states<Fsm>::type, ::boost::mpl::vector0<>,
  732. ::boost::mpl::push_back<
  733. ::boost::mpl::placeholders::_1,
  734. build_one_orthogonal_region< typename Fsm::stt, ::boost::mpl::placeholders::_2 > >
  735. >::type only_entries;
  736. typedef typename ::boost::mpl::fold<
  737. only_entries , without_entries,
  738. add_entry_region< ::boost::mpl::placeholders::_2, ::boost::mpl::placeholders::_1>
  739. >::type type;
  740. };
  741. template <class GraphAsSeqOfSets, class StateType>
  742. struct find_region_index
  743. {
  744. typedef typename
  745. ::boost::mpl::fold<
  746. GraphAsSeqOfSets, ::boost::mpl::pair< ::boost::mpl::int_< -1 > /*res*/, ::boost::mpl::int_<0> /*counter*/ >,
  747. ::boost::mpl::if_<
  748. ::boost::mpl::has_key< ::boost::mpl::placeholders::_2, StateType >,
  749. ::boost::mpl::pair<
  750. ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
  751. ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
  752. >,
  753. ::boost::mpl::pair<
  754. ::boost::mpl::first< ::boost::mpl::placeholders::_1 >,
  755. ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
  756. >
  757. >
  758. >::type result_pair;
  759. typedef typename ::boost::mpl::first<result_pair>::type type;
  760. enum {value = type::value};
  761. };
  762. template <class Fsm>
  763. struct check_regions_orthogonality
  764. {
  765. typedef typename build_orthogonal_regions< Fsm,typename Fsm::initial_states>::type regions;
  766. typedef typename ::boost::mpl::fold<
  767. regions, ::boost::mpl::int_<0>,
  768. ::boost::mpl::plus< ::boost::mpl::placeholders::_1 , ::boost::mpl::size< ::boost::mpl::placeholders::_2> >
  769. >::type number_of_states_in_regions;
  770. typedef typename ::boost::mpl::fold<
  771. regions,mpl::set0<>,
  772. set_insert_range<
  773. ::boost::mpl::placeholders::_1,
  774. ::boost::mpl::placeholders::_2 >
  775. >::type one_big_states_set;
  776. enum {states_in_regions_raw = number_of_states_in_regions::value};
  777. enum {cumulated_states_in_regions_raw = ::boost::mpl::size<one_big_states_set>::value};
  778. };
  779. template <class Fsm>
  780. struct check_no_unreachable_state
  781. {
  782. typedef typename check_regions_orthogonality<Fsm>::one_big_states_set states_in_regions;
  783. typedef typename set_insert_range<
  784. states_in_regions,
  785. typename ::boost::mpl::eval_if<
  786. typename has_explicit_creation<Fsm>::type,
  787. get_explicit_creation<Fsm>,
  788. ::boost::mpl::vector0<>
  789. >::type
  790. >::type with_explicit_creation;
  791. enum {states_in_fsm = ::boost::mpl::size< typename Fsm::substate_list >::value};
  792. enum {cumulated_states_in_regions = ::boost::mpl::size< with_explicit_creation >::value};
  793. };
  794. // helper to find out if a SM has an active exit state and is therefore waiting for exiting
  795. template <class StateType,class OwnerFct,class FSM>
  796. inline
  797. typename ::boost::enable_if<typename ::boost::mpl::and_<typename is_composite_state<FSM>::type,
  798. typename is_pseudo_exit<StateType>::type>,bool >::type
  799. is_exit_state_active(FSM& fsm)
  800. {
  801. typedef typename OwnerFct::type Composite;
  802. //typedef typename create_stt<Composite>::type stt;
  803. typedef typename Composite::stt stt;
  804. int state_id = get_state_id<stt,StateType>::type::value;
  805. Composite& comp = fsm.template get_state<Composite&>();
  806. return (std::find(comp.current_state(),comp.current_state()+Composite::nr_regions::value,state_id)
  807. !=comp.current_state()+Composite::nr_regions::value);
  808. }
  809. template <class StateType,class OwnerFct,class FSM>
  810. inline
  811. typename ::boost::disable_if<typename ::boost::mpl::and_<typename is_composite_state<FSM>::type,
  812. typename is_pseudo_exit<StateType>::type>,bool >::type
  813. is_exit_state_active(FSM&)
  814. {
  815. return false;
  816. }
  817. } } }//boost::msm::back
  818. #endif // BOOST_MSM_BACK_METAFUNCTIONS_H