simple_state.hpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. #ifndef BOOST_STATECHART_SIMPLE_STATE_HPP_INCLUDED
  2. #define BOOST_STATECHART_SIMPLE_STATE_HPP_INCLUDED
  3. //////////////////////////////////////////////////////////////////////////////
  4. // Copyright 2002-2010 Andreas Huber Doenni
  5. // Distributed under the Boost Software License, Version 1.0. (See accompany-
  6. // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. //////////////////////////////////////////////////////////////////////////////
  8. #include <boost/statechart/event.hpp>
  9. #include <boost/statechart/detail/leaf_state.hpp>
  10. #include <boost/statechart/detail/node_state.hpp>
  11. #include <boost/statechart/detail/constructor.hpp>
  12. #include <boost/statechart/detail/memory.hpp>
  13. #include <boost/mpl/eval_if.hpp>
  14. #include <boost/mpl/if.hpp>
  15. #include <boost/mpl/identity.hpp>
  16. #include <boost/mpl/is_sequence.hpp>
  17. #include <boost/mpl/list.hpp>
  18. #include <boost/mpl/empty.hpp>
  19. #include <boost/mpl/size.hpp>
  20. #include <boost/mpl/front.hpp>
  21. #include <boost/mpl/at.hpp>
  22. #include <boost/mpl/find.hpp>
  23. #include <boost/mpl/find_if.hpp>
  24. #include <boost/mpl/contains.hpp>
  25. #include <boost/mpl/distance.hpp>
  26. #include <boost/mpl/deref.hpp>
  27. #include <boost/mpl/pop_front.hpp>
  28. #include <boost/mpl/push_front.hpp>
  29. #include <boost/mpl/clear.hpp>
  30. #include <boost/mpl/placeholders.hpp>
  31. #include <boost/mpl/bool.hpp>
  32. #include <boost/mpl/integral_c.hpp>
  33. #include <boost/mpl/less.hpp>
  34. #include <boost/mpl/equal_to.hpp>
  35. #include <boost/mpl/not.hpp>
  36. #include <boost/mpl/or.hpp>
  37. #include <boost/mpl/plus.hpp>
  38. #include <boost/mpl/max_element.hpp>
  39. #include <boost/mpl/greater.hpp>
  40. #include <boost/get_pointer.hpp>
  41. #include <boost/intrusive_ptr.hpp>
  42. #include <boost/assert.hpp>
  43. #include <boost/type_traits/is_base_of.hpp>
  44. #include <boost/type_traits/is_same.hpp>
  45. #include <boost/static_assert.hpp>
  46. #include <boost/polymorphic_cast.hpp> // boost::polymorphic_downcast
  47. #include <cstddef> // std::size_t
  48. namespace boost
  49. {
  50. namespace statechart
  51. {
  52. namespace detail
  53. {
  54. //////////////////////////////////////////////////////////////////////////////
  55. template< class T >
  56. struct make_list : public mpl::eval_if<
  57. mpl::is_sequence< T >,
  58. mpl::identity< T >,
  59. mpl::identity< mpl::list< T > > > {};
  60. //////////////////////////////////////////////////////////////////////////////
  61. template< class MostDerived, class Context, class InnerInitial >
  62. struct simple_state_base_type
  63. {
  64. private:
  65. typedef typename Context::outermost_context_base_type::allocator_type
  66. allocator_type;
  67. typedef typename Context::outermost_context_base_type::rtti_policy_type
  68. rtti_policy_type;
  69. typedef typename detail::make_list< InnerInitial >::type
  70. inner_initial_list;
  71. typedef typename mpl::size< inner_initial_list >::type
  72. inner_initial_list_size;
  73. public:
  74. typedef typename mpl::eval_if<
  75. mpl::empty< inner_initial_list >,
  76. mpl::identity< typename rtti_policy_type::
  77. template rtti_derived_type< MostDerived, leaf_state<
  78. allocator_type,
  79. rtti_policy_type > > >,
  80. mpl::identity< typename rtti_policy_type::
  81. template rtti_derived_type< MostDerived, node_state<
  82. inner_initial_list_size,
  83. allocator_type,
  84. rtti_policy_type > > > >::type type;
  85. };
  86. //////////////////////////////////////////////////////////////////////////////
  87. struct no_transition_function
  88. {
  89. template< class CommonContext >
  90. void operator()( CommonContext & ) const {}
  91. };
  92. template< class TransitionContext, class Event >
  93. class transition_function
  94. {
  95. public:
  96. transition_function(
  97. void ( TransitionContext::*pTransitionAction )( const Event & ),
  98. const Event & evt
  99. ) :
  100. pTransitionAction_( pTransitionAction ),
  101. evt_( evt )
  102. {
  103. }
  104. template< class CommonContext >
  105. void operator()( CommonContext & commonContext ) const
  106. {
  107. ( commonContext.template context< TransitionContext >()
  108. .*pTransitionAction_ )( evt_ );
  109. }
  110. private:
  111. // avoids C4512 (assignment operator could not be generated)
  112. transition_function & operator=( const transition_function & );
  113. void ( TransitionContext::*pTransitionAction_ )( const Event & );
  114. const Event & evt_;
  115. };
  116. template< bool contextHasInheritedDeepHistory, bool contextHasDeepHistory >
  117. struct deep_history_storer
  118. {
  119. template< class HistorizedState, class LeafState, class Context >
  120. static void store_deep_history( Context & ) {}
  121. };
  122. template<>
  123. struct deep_history_storer< true, false >
  124. {
  125. template< class HistorizedState, class LeafState, class Context >
  126. static void store_deep_history( Context & ctx )
  127. {
  128. ctx.template store_deep_history_impl< LeafState >();
  129. }
  130. };
  131. template<>
  132. struct deep_history_storer< true, true >
  133. {
  134. template< class HistorizedState, class LeafState, class Context >
  135. static void store_deep_history( Context & ctx )
  136. {
  137. ctx.outermost_context_base().template store_deep_history<
  138. HistorizedState, LeafState >();
  139. ctx.template store_deep_history_impl< LeafState >();
  140. }
  141. };
  142. } // namespace detail
  143. //////////////////////////////////////////////////////////////////////////////
  144. enum history_mode
  145. {
  146. has_no_history,
  147. has_shallow_history,
  148. has_deep_history,
  149. has_full_history // shallow & deep
  150. };
  151. //////////////////////////////////////////////////////////////////////////////
  152. template< class MostDerived,
  153. class Context,
  154. class InnerInitial = mpl::list<>,
  155. history_mode historyMode = has_no_history >
  156. class simple_state : public detail::simple_state_base_type< MostDerived,
  157. typename Context::inner_context_type, InnerInitial >::type
  158. {
  159. typedef typename detail::simple_state_base_type<
  160. MostDerived, typename Context::inner_context_type,
  161. InnerInitial >::type base_type;
  162. public:
  163. //////////////////////////////////////////////////////////////////////////
  164. typedef mpl::list<> reactions;
  165. typedef typename Context::inner_context_type context_type;
  166. template< detail::orthogonal_position_type innerOrthogonalPosition >
  167. struct orthogonal
  168. {
  169. typedef mpl::integral_c<
  170. detail::orthogonal_position_type,
  171. innerOrthogonalPosition > inner_orthogonal_position;
  172. typedef MostDerived inner_context_type;
  173. };
  174. typedef typename context_type::outermost_context_type
  175. outermost_context_type;
  176. outermost_context_type & outermost_context()
  177. {
  178. // This assert fails when an attempt is made to access the state machine
  179. // from a constructor of a state that is *not* a subtype of state<>.
  180. // To correct this, derive from state<> instead of simple_state<>.
  181. BOOST_ASSERT( get_pointer( pContext_ ) != 0 );
  182. return pContext_->outermost_context();
  183. }
  184. const outermost_context_type & outermost_context() const
  185. {
  186. // This assert fails when an attempt is made to access the state machine
  187. // from a constructor of a state that is *not* a subtype of state<>.
  188. // To correct this, derive from state<> instead of simple_state<>.
  189. BOOST_ASSERT( get_pointer( pContext_ ) != 0 );
  190. return pContext_->outermost_context();
  191. }
  192. template< class OtherContext >
  193. OtherContext & context()
  194. {
  195. typedef typename mpl::if_<
  196. is_base_of< OtherContext, MostDerived >,
  197. context_impl_this_context,
  198. context_impl_other_context
  199. >::type impl;
  200. return impl::template context_impl< OtherContext >( *this );
  201. }
  202. template< class OtherContext >
  203. const OtherContext & context() const
  204. {
  205. typedef typename mpl::if_<
  206. is_base_of< OtherContext, MostDerived >,
  207. context_impl_this_context,
  208. context_impl_other_context
  209. >::type impl;
  210. return impl::template context_impl< OtherContext >( *this );
  211. }
  212. template< class Target >
  213. Target state_cast() const
  214. {
  215. return outermost_context_base().template state_cast< Target >();
  216. }
  217. template< class Target >
  218. Target state_downcast() const
  219. {
  220. return outermost_context_base().template state_downcast< Target >();
  221. }
  222. typedef typename context_type::state_base_type state_base_type;
  223. typedef typename context_type::state_iterator state_iterator;
  224. state_iterator state_begin() const
  225. {
  226. return outermost_context_base().state_begin();
  227. }
  228. state_iterator state_end() const
  229. {
  230. return outermost_context_base().state_end();
  231. }
  232. typedef typename context_type::event_base_ptr_type event_base_ptr_type;
  233. void post_event( const event_base_ptr_type & pEvent )
  234. {
  235. outermost_context_base().post_event_impl( pEvent );
  236. }
  237. void post_event( const event_base & evt )
  238. {
  239. outermost_context_base().post_event_impl( evt );
  240. }
  241. result discard_event()
  242. {
  243. return detail::result_utility::make_result( detail::do_discard_event );
  244. }
  245. result forward_event()
  246. {
  247. return detail::result_utility::make_result( detail::do_forward_event );
  248. }
  249. result defer_event()
  250. {
  251. this->state_base_type::defer_event();
  252. return detail::result_utility::make_result( detail::do_defer_event );
  253. }
  254. template< class DestinationState >
  255. result transit()
  256. {
  257. return transit_impl< DestinationState, outermost_context_type >(
  258. detail::no_transition_function() );
  259. }
  260. template< class DestinationState, class TransitionContext, class Event >
  261. result transit(
  262. void ( TransitionContext::*pTransitionAction )( const Event & ),
  263. const Event & evt )
  264. {
  265. return transit_impl< DestinationState, TransitionContext >(
  266. detail::transition_function< TransitionContext, Event >(
  267. pTransitionAction, evt ) );
  268. }
  269. result terminate()
  270. {
  271. outermost_context_base().terminate_as_reaction( *this );
  272. return detail::result_utility::make_result( detail::do_discard_event );
  273. }
  274. template<
  275. class HistoryContext,
  276. detail::orthogonal_position_type orthogonalPosition >
  277. void clear_shallow_history()
  278. {
  279. outermost_context_base().template clear_shallow_history<
  280. HistoryContext, orthogonalPosition >();
  281. }
  282. template<
  283. class HistoryContext,
  284. detail::orthogonal_position_type orthogonalPosition >
  285. void clear_deep_history()
  286. {
  287. outermost_context_base().template clear_deep_history<
  288. HistoryContext, orthogonalPosition >();
  289. }
  290. const event_base * triggering_event() const
  291. {
  292. return outermost_context_base().triggering_event();
  293. }
  294. protected:
  295. //////////////////////////////////////////////////////////////////////////
  296. simple_state() : pContext_( 0 ) {}
  297. ~simple_state()
  298. {
  299. // As a result of a throwing derived class constructor, this destructor
  300. // can be called before the context is set.
  301. if ( get_pointer( pContext_ ) != 0 )
  302. {
  303. if ( this->deferred_events() )
  304. {
  305. outermost_context_base().release_events();
  306. }
  307. pContext_->remove_inner_state( orthogonal_position::value );
  308. }
  309. }
  310. public:
  311. //////////////////////////////////////////////////////////////////////////
  312. // The following declarations should be private.
  313. // They are only public because many compilers lack template friends.
  314. //////////////////////////////////////////////////////////////////////////
  315. typedef typename Context::inner_orthogonal_position orthogonal_position;
  316. // If you receive a
  317. // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or similar
  318. // compiler error here then either this state resides in a non-existent
  319. // orthogonal region of the outer state or the outer state does not have
  320. // inner states.
  321. BOOST_STATIC_ASSERT( ( mpl::less<
  322. orthogonal_position,
  323. typename context_type::no_of_orthogonal_regions >::value ) );
  324. typedef MostDerived inner_context_type;
  325. typedef mpl::integral_c< detail::orthogonal_position_type, 0 >
  326. inner_orthogonal_position;
  327. typedef typename context_type::event_base_type event_base_type;
  328. typedef typename context_type::rtti_policy_type rtti_policy_type;
  329. typedef typename context_type::outermost_context_base_type
  330. outermost_context_base_type;
  331. typedef typename context_type::inner_context_ptr_type context_ptr_type;
  332. typedef typename context_type::state_list_type state_list_type;
  333. typedef intrusive_ptr< inner_context_type > inner_context_ptr_type;
  334. typedef typename detail::make_list< InnerInitial >::type
  335. inner_initial_list;
  336. typedef typename mpl::size< inner_initial_list >::type
  337. inner_initial_list_size;
  338. typedef mpl::integral_c<
  339. detail::orthogonal_position_type,
  340. inner_initial_list_size::value > no_of_orthogonal_regions;
  341. typedef typename mpl::push_front<
  342. typename context_type::context_type_list,
  343. context_type >::type context_type_list;
  344. // If you receive a
  345. // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or similar
  346. // compiler error here then the direct or indirect context of this state
  347. // has deep history _and_ this state has two or more orthogonal regions.
  348. // Boost.Statechart does not currently support deep history in a state whose
  349. // direct or indirect inner states have two or more orthogonal regions.
  350. // Please consult the documentation on how to work around this limitation.
  351. BOOST_STATIC_ASSERT( ( mpl::or_<
  352. mpl::less<
  353. no_of_orthogonal_regions,
  354. mpl::integral_c< detail::orthogonal_position_type, 2 > >,
  355. mpl::not_<
  356. typename context_type::inherited_deep_history > >::value ) );
  357. typedef mpl::bool_< ( historyMode & has_shallow_history ) != 0 >
  358. shallow_history;
  359. typedef typename context_type::shallow_history stores_shallow_history;
  360. typedef mpl::bool_< ( historyMode & has_deep_history ) != 0 >
  361. deep_history;
  362. typedef typename mpl::or_<
  363. deep_history,
  364. typename context_type::inherited_deep_history
  365. >::type inherited_deep_history;
  366. typedef typename mpl::and_<
  367. inherited_deep_history,
  368. mpl::empty< inner_initial_list > >::type stores_deep_history;
  369. void * operator new( std::size_t size )
  370. {
  371. return detail::allocate< MostDerived,
  372. typename outermost_context_type::allocator_type >( size );
  373. }
  374. void operator delete( void * pState )
  375. {
  376. detail::deallocate< MostDerived,
  377. typename outermost_context_type::allocator_type >( pState );
  378. }
  379. outermost_context_base_type & outermost_context_base()
  380. {
  381. // This assert fails when an attempt is made to access the state machine
  382. // from a constructor of a state that is *not* a subtype of state<>.
  383. // To correct this, derive from state<> instead of simple_state<>.
  384. BOOST_ASSERT( get_pointer( pContext_ ) != 0 );
  385. return pContext_->outermost_context_base();
  386. }
  387. const outermost_context_base_type & outermost_context_base() const
  388. {
  389. // This assert fails when an attempt is made to access the state machine
  390. // from a constructor of a state that is *not* a subtype of state<>.
  391. // To correct this, derive from state<> instead of simple_state<>.
  392. BOOST_ASSERT( get_pointer( pContext_ ) != 0 );
  393. return pContext_->outermost_context_base();
  394. }
  395. virtual const state_base_type * outer_state_ptr() const
  396. {
  397. typedef typename mpl::if_<
  398. is_same< outermost_context_type, context_type >,
  399. outer_state_ptr_impl_outermost,
  400. outer_state_ptr_impl_non_outermost
  401. >::type impl;
  402. return impl::outer_state_ptr_impl( *this );
  403. }
  404. virtual detail::reaction_result react_impl(
  405. const event_base_type & evt,
  406. typename rtti_policy_type::id_type eventType )
  407. {
  408. typedef typename detail::make_list<
  409. typename MostDerived::reactions >::type reaction_list;
  410. detail::reaction_result reactionResult =
  411. local_react< reaction_list >( evt, eventType );
  412. // At this point we can only safely access pContext_ if the handler did
  413. // not return do_discard_event!
  414. if ( reactionResult == detail::do_forward_event )
  415. {
  416. // TODO: The following call to react_impl of our outer state should
  417. // be made with a context_type:: prefix to call directly instead of
  418. // virtually. For some reason the compiler complains...
  419. reactionResult = pContext_->react_impl( evt, eventType );
  420. }
  421. return reactionResult;
  422. }
  423. virtual void exit_impl(
  424. typename base_type::direct_state_base_ptr_type & pSelf,
  425. typename state_base_type::node_state_base_ptr_type &
  426. pOutermostUnstableState,
  427. bool performFullExit )
  428. {
  429. inner_context_ptr_type pMostDerivedSelf =
  430. polymorphic_downcast< MostDerived * >( this );
  431. pSelf = 0;
  432. exit_impl( pMostDerivedSelf, pOutermostUnstableState, performFullExit );
  433. }
  434. void exit_impl(
  435. inner_context_ptr_type & pSelf,
  436. typename state_base_type::node_state_base_ptr_type &
  437. pOutermostUnstableState,
  438. bool performFullExit )
  439. {
  440. switch ( this->ref_count() )
  441. {
  442. case 2:
  443. if ( get_pointer( pOutermostUnstableState ) ==
  444. static_cast< state_base_type * >( this ) )
  445. {
  446. pContext_->set_outermost_unstable_state(
  447. pOutermostUnstableState );
  448. BOOST_FALLTHROUGH;
  449. }
  450. else
  451. {
  452. break;
  453. }
  454. case 1:
  455. {
  456. if ( get_pointer( pOutermostUnstableState ) == 0 )
  457. {
  458. pContext_->set_outermost_unstable_state(
  459. pOutermostUnstableState );
  460. }
  461. if ( performFullExit )
  462. {
  463. pSelf->exit();
  464. check_store_shallow_history< stores_shallow_history >();
  465. check_store_deep_history< stores_deep_history >();
  466. }
  467. context_ptr_type pContext = pContext_;
  468. pSelf = 0;
  469. pContext->exit_impl(
  470. pContext, pOutermostUnstableState, performFullExit );
  471. break;
  472. }
  473. default:
  474. break;
  475. }
  476. }
  477. void set_outermost_unstable_state(
  478. typename state_base_type::node_state_base_ptr_type &
  479. pOutermostUnstableState )
  480. {
  481. pOutermostUnstableState = this;
  482. }
  483. template< class OtherContext >
  484. const typename OtherContext::inner_context_ptr_type & context_ptr() const
  485. {
  486. typedef typename mpl::if_<
  487. is_same< OtherContext, context_type >,
  488. context_ptr_impl_my_context,
  489. context_ptr_impl_other_context
  490. >::type impl;
  491. return impl::template context_ptr_impl< OtherContext >( *this );
  492. }
  493. static void initial_deep_construct(
  494. outermost_context_base_type & outermostContextBase )
  495. {
  496. deep_construct( &outermostContextBase, outermostContextBase );
  497. }
  498. static void deep_construct(
  499. const context_ptr_type & pContext,
  500. outermost_context_base_type & outermostContextBase )
  501. {
  502. const inner_context_ptr_type pInnerContext(
  503. shallow_construct( pContext, outermostContextBase ) );
  504. deep_construct_inner< inner_initial_list >(
  505. pInnerContext, outermostContextBase );
  506. }
  507. static inner_context_ptr_type shallow_construct(
  508. const context_ptr_type & pContext,
  509. outermost_context_base_type & outermostContextBase )
  510. {
  511. const inner_context_ptr_type pInnerContext( new MostDerived );
  512. pInnerContext->set_context( pContext );
  513. outermostContextBase.add( pInnerContext );
  514. return pInnerContext;
  515. }
  516. void set_context( const context_ptr_type & pContext )
  517. {
  518. BOOST_ASSERT( get_pointer( pContext ) != 0 );
  519. pContext_ = pContext;
  520. base_type::set_context(
  521. orthogonal_position::value, get_pointer( pContext ) );
  522. }
  523. template< class InnerList >
  524. static void deep_construct_inner(
  525. const inner_context_ptr_type & pInnerContext,
  526. outermost_context_base_type & outermostContextBase )
  527. {
  528. typedef typename mpl::if_<
  529. mpl::empty< InnerList >,
  530. deep_construct_inner_impl_empty,
  531. deep_construct_inner_impl_non_empty
  532. >::type impl;
  533. impl::template deep_construct_inner_impl< InnerList >(
  534. pInnerContext, outermostContextBase );
  535. }
  536. template< class LeafState >
  537. void store_deep_history_impl()
  538. {
  539. detail::deep_history_storer<
  540. context_type::inherited_deep_history::value,
  541. context_type::deep_history::value
  542. >::template store_deep_history< MostDerived, LeafState >(
  543. *pContext_ );
  544. }
  545. private:
  546. //////////////////////////////////////////////////////////////////////////
  547. struct context_ptr_impl_other_context
  548. {
  549. template< class OtherContext, class State >
  550. static const typename OtherContext::inner_context_ptr_type &
  551. context_ptr_impl( const State & stt )
  552. {
  553. // This assert fails when an attempt is made to access an outer
  554. // context from a constructor of a state that is *not* a subtype of
  555. // state<>. To correct this, derive from state<> instead of
  556. // simple_state<>.
  557. BOOST_ASSERT( get_pointer( stt.pContext_ ) != 0 );
  558. return stt.pContext_->template context_ptr< OtherContext >();
  559. }
  560. };
  561. friend struct context_ptr_impl_other_context;
  562. struct context_ptr_impl_my_context
  563. {
  564. template< class OtherContext, class State >
  565. static const typename OtherContext::inner_context_ptr_type &
  566. context_ptr_impl( const State & stt )
  567. {
  568. // This assert fails when an attempt is made to access an outer
  569. // context from a constructor of a state that is *not* a subtype of
  570. // state<>. To correct this, derive from state<> instead of
  571. // simple_state<>.
  572. BOOST_ASSERT( get_pointer( stt.pContext_ ) != 0 );
  573. return stt.pContext_;
  574. }
  575. };
  576. friend struct context_ptr_impl_my_context;
  577. struct context_impl_other_context
  578. {
  579. template< class OtherContext, class State >
  580. static OtherContext & context_impl( State & stt )
  581. {
  582. // This assert fails when an attempt is made to access an outer
  583. // context from a constructor of a state that is *not* a subtype of
  584. // state<>. To correct this, derive from state<> instead of
  585. // simple_state<>.
  586. BOOST_ASSERT( get_pointer( stt.pContext_ ) != 0 );
  587. return stt.pContext_->template context< OtherContext >();
  588. }
  589. };
  590. friend struct context_impl_other_context;
  591. struct context_impl_this_context
  592. {
  593. template< class OtherContext, class State >
  594. static OtherContext & context_impl( State & stt )
  595. {
  596. return *polymorphic_downcast< MostDerived * >( &stt );
  597. }
  598. };
  599. friend struct context_impl_this_context;
  600. template< class DestinationState,
  601. class TransitionContext,
  602. class TransitionAction >
  603. result transit_impl( const TransitionAction & transitionAction )
  604. {
  605. typedef typename mpl::find_if<
  606. context_type_list,
  607. mpl::contains<
  608. typename DestinationState::context_type_list,
  609. mpl::placeholders::_ > >::type common_context_iter;
  610. typedef typename mpl::deref< common_context_iter >::type
  611. common_context_type;
  612. typedef typename mpl::distance<
  613. typename mpl::begin< context_type_list >::type,
  614. common_context_iter >::type termination_state_position;
  615. typedef typename mpl::push_front< context_type_list, MostDerived >::type
  616. possible_transition_contexts;
  617. typedef typename mpl::at<
  618. possible_transition_contexts,
  619. termination_state_position >::type termination_state_type;
  620. termination_state_type & terminationState(
  621. context< termination_state_type >() );
  622. const typename
  623. common_context_type::inner_context_ptr_type pCommonContext(
  624. terminationState.template context_ptr< common_context_type >() );
  625. outermost_context_base_type & outermostContextBase(
  626. pCommonContext->outermost_context_base() );
  627. #ifdef BOOST_STATECHART_RELAX_TRANSITION_CONTEXT
  628. typedef typename mpl::distance<
  629. typename mpl::begin< possible_transition_contexts >::type,
  630. typename mpl::find<
  631. possible_transition_contexts, TransitionContext >::type
  632. >::type proposed_transition_context_position;
  633. typedef typename mpl::plus<
  634. termination_state_position,
  635. mpl::long_< 1 >
  636. >::type uml_transition_context_position;
  637. typedef typename mpl::deref< typename mpl::max_element<
  638. mpl::list<
  639. proposed_transition_context_position,
  640. uml_transition_context_position >,
  641. mpl::greater< mpl::placeholders::_, mpl::placeholders::_ >
  642. >::type >::type real_transition_context_position;
  643. typedef typename mpl::at<
  644. possible_transition_contexts,
  645. real_transition_context_position >::type real_transition_context_type;
  646. #ifdef BOOST_MSVC
  647. # pragma warning( push )
  648. # pragma warning( disable: 4127 ) // conditional expression is constant
  649. #endif
  650. if ( ( proposed_transition_context_position::value == 0 ) &&
  651. ( inner_initial_list_size::value == 0 ) )
  652. {
  653. transitionAction( *polymorphic_downcast< MostDerived * >( this ) );
  654. outermostContextBase.terminate_as_part_of_transit( terminationState );
  655. }
  656. else if ( proposed_transition_context_position::value >=
  657. uml_transition_context_position::value )
  658. {
  659. real_transition_context_type & transitionContext =
  660. context< real_transition_context_type >();
  661. outermostContextBase.terminate_as_part_of_transit( terminationState );
  662. transitionAction( transitionContext );
  663. }
  664. else
  665. {
  666. typename real_transition_context_type::inner_context_ptr_type
  667. pTransitionContext = context_ptr< real_transition_context_type >();
  668. outermostContextBase.terminate_as_part_of_transit(
  669. *pTransitionContext );
  670. transitionAction( *pTransitionContext );
  671. pTransitionContext = 0;
  672. outermostContextBase.terminate_as_part_of_transit( terminationState );
  673. }
  674. #ifdef BOOST_MSVC
  675. # pragma warning( pop )
  676. #endif
  677. #else
  678. outermostContextBase.terminate_as_part_of_transit( terminationState );
  679. transitionAction( *pCommonContext );
  680. #endif
  681. typedef typename detail::make_context_list<
  682. common_context_type, DestinationState >::type context_list_type;
  683. // If you receive a
  684. // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or
  685. // similar compiler error here then you tried to make an invalid
  686. // transition between different orthogonal regions.
  687. BOOST_STATIC_ASSERT( ( mpl::equal_to<
  688. typename termination_state_type::orthogonal_position,
  689. typename mpl::front< context_list_type >::type::orthogonal_position
  690. >::value ) );
  691. detail::constructor<
  692. context_list_type, outermost_context_base_type >::construct(
  693. pCommonContext, outermostContextBase );
  694. return detail::result_utility::make_result( detail::do_discard_event );
  695. }
  696. struct local_react_impl_non_empty
  697. {
  698. template< class ReactionList, class State >
  699. static detail::reaction_result local_react_impl(
  700. State & stt,
  701. const event_base_type & evt,
  702. typename rtti_policy_type::id_type eventType )
  703. {
  704. detail::reaction_result reactionResult =
  705. mpl::front< ReactionList >::type::react(
  706. *polymorphic_downcast< MostDerived * >( &stt ),
  707. evt, eventType );
  708. if ( reactionResult == detail::no_reaction )
  709. {
  710. reactionResult = stt.template local_react<
  711. typename mpl::pop_front< ReactionList >::type >(
  712. evt, eventType );
  713. }
  714. return reactionResult;
  715. }
  716. };
  717. friend struct local_react_impl_non_empty;
  718. struct local_react_impl_empty
  719. {
  720. template< class ReactionList, class State >
  721. static detail::reaction_result local_react_impl(
  722. State &, const event_base_type &, typename rtti_policy_type::id_type )
  723. {
  724. return detail::do_forward_event;
  725. }
  726. };
  727. template< class ReactionList >
  728. detail::reaction_result local_react(
  729. const event_base_type & evt,
  730. typename rtti_policy_type::id_type eventType )
  731. {
  732. typedef typename mpl::if_<
  733. mpl::empty< ReactionList >,
  734. local_react_impl_empty,
  735. local_react_impl_non_empty
  736. >::type impl;
  737. return impl::template local_react_impl< ReactionList >(
  738. *this, evt, eventType );
  739. }
  740. struct outer_state_ptr_impl_non_outermost
  741. {
  742. template< class State >
  743. static const state_base_type * outer_state_ptr_impl( const State & stt )
  744. {
  745. return get_pointer( stt.pContext_ );
  746. }
  747. };
  748. friend struct outer_state_ptr_impl_non_outermost;
  749. struct outer_state_ptr_impl_outermost
  750. {
  751. template< class State >
  752. static const state_base_type * outer_state_ptr_impl( const State & )
  753. {
  754. return 0;
  755. }
  756. };
  757. struct deep_construct_inner_impl_non_empty
  758. {
  759. template< class InnerList >
  760. static void deep_construct_inner_impl(
  761. const inner_context_ptr_type & pInnerContext,
  762. outermost_context_base_type & outermostContextBase )
  763. {
  764. typedef typename mpl::front< InnerList >::type current_inner;
  765. // If you receive a
  766. // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or
  767. // similar compiler error here then there is a mismatch between the
  768. // orthogonal position of a state and its position in the inner
  769. // initial list of its outer state.
  770. BOOST_STATIC_ASSERT( ( is_same<
  771. current_inner,
  772. typename mpl::at<
  773. typename current_inner::context_type::inner_initial_list,
  774. typename current_inner::orthogonal_position >::type >::value ) );
  775. current_inner::deep_construct( pInnerContext, outermostContextBase );
  776. deep_construct_inner< typename mpl::pop_front< InnerList >::type >(
  777. pInnerContext, outermostContextBase );
  778. }
  779. };
  780. struct deep_construct_inner_impl_empty
  781. {
  782. template< class InnerList >
  783. static void deep_construct_inner_impl(
  784. const inner_context_ptr_type &, outermost_context_base_type & ) {}
  785. };
  786. struct check_store_shallow_history_impl_no
  787. {
  788. template< class State >
  789. static void check_store_shallow_history_impl( State & ) {}
  790. };
  791. struct check_store_shallow_history_impl_yes
  792. {
  793. template< class State >
  794. static void check_store_shallow_history_impl( State & stt )
  795. {
  796. stt.outermost_context_base().template store_shallow_history<
  797. MostDerived >();
  798. }
  799. };
  800. friend struct check_store_shallow_history_impl_yes;
  801. template< class StoreShallowHistory >
  802. void check_store_shallow_history()
  803. {
  804. typedef typename mpl::if_<
  805. StoreShallowHistory,
  806. check_store_shallow_history_impl_yes,
  807. check_store_shallow_history_impl_no
  808. >::type impl;
  809. impl::check_store_shallow_history_impl( *this );
  810. }
  811. struct check_store_deep_history_impl_no
  812. {
  813. template< class State >
  814. static void check_store_deep_history_impl( State & ) {}
  815. };
  816. struct check_store_deep_history_impl_yes
  817. {
  818. template< class State >
  819. static void check_store_deep_history_impl( State & stt )
  820. {
  821. stt.template store_deep_history_impl< MostDerived >();
  822. }
  823. };
  824. friend struct check_store_deep_history_impl_yes;
  825. template< class StoreDeepHistory >
  826. void check_store_deep_history()
  827. {
  828. typedef typename mpl::if_<
  829. StoreDeepHistory,
  830. check_store_deep_history_impl_yes,
  831. check_store_deep_history_impl_no
  832. >::type impl;
  833. impl::check_store_deep_history_impl( *this );
  834. }
  835. context_ptr_type pContext_;
  836. };
  837. #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
  838. } // namespace statechart
  839. #endif
  840. template< class MostDerived, class Context,
  841. class InnerInitial, history_mode historyMode >
  842. inline void intrusive_ptr_release( const ::boost::statechart::simple_state<
  843. MostDerived, Context, InnerInitial, historyMode > * pBase )
  844. {
  845. if ( pBase->release() )
  846. {
  847. // The cast is necessary because the simple_state destructor is non-
  848. // virtual (and inaccessible from this context)
  849. delete polymorphic_downcast< const MostDerived * >( pBase );
  850. }
  851. }
  852. #ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
  853. } // namespace statechart
  854. #endif
  855. } // namespace boost
  856. #endif