Chris@16: #ifndef BOOST_STATECHART_SIMPLE_STATE_HPP_INCLUDED Chris@16: #define BOOST_STATECHART_SIMPLE_STATE_HPP_INCLUDED Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Copyright 2002-2010 Andreas Huber Doenni Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompany- Chris@16: // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include // boost::polymorphic_downcast Chris@16: Chris@16: #include // std::size_t Chris@16: Chris@16: Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: namespace statechart Chris@16: { Chris@16: namespace detail Chris@16: { Chris@16: Chris@16: Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: template< class T > Chris@16: struct make_list : public mpl::eval_if< Chris@16: mpl::is_sequence< T >, Chris@16: mpl::identity< T >, Chris@16: mpl::identity< mpl::list< T > > > {}; Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: template< class MostDerived, class Context, class InnerInitial > Chris@16: struct simple_state_base_type Chris@16: { Chris@16: private: Chris@16: typedef typename Context::outermost_context_base_type::allocator_type Chris@16: allocator_type; Chris@16: typedef typename Context::outermost_context_base_type::rtti_policy_type Chris@16: rtti_policy_type; Chris@16: typedef typename detail::make_list< InnerInitial >::type Chris@16: inner_initial_list; Chris@16: typedef typename mpl::size< inner_initial_list >::type Chris@16: inner_initial_list_size; Chris@16: Chris@16: public: Chris@16: typedef typename mpl::eval_if< Chris@16: mpl::empty< inner_initial_list >, Chris@16: mpl::identity< typename rtti_policy_type:: Chris@16: template rtti_derived_type< MostDerived, leaf_state< Chris@16: allocator_type, Chris@16: rtti_policy_type > > >, Chris@16: mpl::identity< typename rtti_policy_type:: Chris@16: template rtti_derived_type< MostDerived, node_state< Chris@16: inner_initial_list_size, Chris@16: allocator_type, Chris@16: rtti_policy_type > > > >::type type; Chris@16: }; Chris@16: Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: struct no_transition_function Chris@16: { Chris@16: template< class CommonContext > Chris@16: void operator()( CommonContext & ) const {} Chris@16: }; Chris@16: Chris@16: template< class TransitionContext, class Event > Chris@16: class transition_function Chris@16: { Chris@16: public: Chris@16: transition_function( Chris@16: void ( TransitionContext::*pTransitionAction )( const Event & ), Chris@16: const Event & evt Chris@16: ) : Chris@16: pTransitionAction_( pTransitionAction ), Chris@16: evt_( evt ) Chris@16: { Chris@16: } Chris@16: Chris@16: template< class CommonContext > Chris@16: void operator()( CommonContext & commonContext ) const Chris@16: { Chris@16: ( commonContext.template context< TransitionContext >() Chris@16: .*pTransitionAction_ )( evt_ ); Chris@16: } Chris@16: Chris@16: private: Chris@16: // avoids C4512 (assignment operator could not be generated) Chris@16: transition_function & operator=( const transition_function & ); Chris@16: Chris@16: void ( TransitionContext::*pTransitionAction_ )( const Event & ); Chris@16: const Event & evt_; Chris@16: }; Chris@16: Chris@16: Chris@16: template< bool contextHasInheritedDeepHistory, bool contextHasDeepHistory > Chris@16: struct deep_history_storer Chris@16: { Chris@16: template< class HistorizedState, class LeafState, class Context > Chris@16: static void store_deep_history( Context & ) {} Chris@16: }; Chris@16: Chris@16: template<> Chris@16: struct deep_history_storer< true, false > Chris@16: { Chris@16: template< class HistorizedState, class LeafState, class Context > Chris@16: static void store_deep_history( Context & ctx ) Chris@16: { Chris@16: ctx.template store_deep_history_impl< LeafState >(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template<> Chris@16: struct deep_history_storer< true, true > Chris@16: { Chris@16: template< class HistorizedState, class LeafState, class Context > Chris@16: static void store_deep_history( Context & ctx ) Chris@16: { Chris@16: ctx.outermost_context_base().template store_deep_history< Chris@16: HistorizedState, LeafState >(); Chris@16: ctx.template store_deep_history_impl< LeafState >(); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: enum history_mode Chris@16: { Chris@16: has_no_history, Chris@16: has_shallow_history, Chris@16: has_deep_history, Chris@16: has_full_history // shallow & deep Chris@16: }; Chris@16: Chris@16: Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: template< class MostDerived, Chris@16: class Context, Chris@16: class InnerInitial = mpl::list<>, Chris@16: history_mode historyMode = has_no_history > Chris@16: class simple_state : public detail::simple_state_base_type< MostDerived, Chris@16: typename Context::inner_context_type, InnerInitial >::type Chris@16: { Chris@16: typedef typename detail::simple_state_base_type< Chris@16: MostDerived, typename Context::inner_context_type, Chris@16: InnerInitial >::type base_type; Chris@16: Chris@16: public: Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: typedef mpl::list<> reactions; Chris@16: Chris@16: typedef typename Context::inner_context_type context_type; Chris@16: Chris@16: template< detail::orthogonal_position_type innerOrthogonalPosition > Chris@16: struct orthogonal Chris@16: { Chris@16: typedef mpl::integral_c< Chris@16: detail::orthogonal_position_type, Chris@16: innerOrthogonalPosition > inner_orthogonal_position; Chris@16: typedef MostDerived inner_context_type; Chris@16: }; Chris@16: Chris@16: typedef typename context_type::outermost_context_type Chris@16: outermost_context_type; Chris@16: Chris@16: outermost_context_type & outermost_context() Chris@16: { Chris@16: // This assert fails when an attempt is made to access the state machine Chris@16: // from a constructor of a state that is *not* a subtype of state<>. Chris@16: // To correct this, derive from state<> instead of simple_state<>. Chris@16: BOOST_ASSERT( get_pointer( pContext_ ) != 0 ); Chris@16: return pContext_->outermost_context(); Chris@16: } Chris@16: Chris@16: const outermost_context_type & outermost_context() const Chris@16: { Chris@16: // This assert fails when an attempt is made to access the state machine Chris@16: // from a constructor of a state that is *not* a subtype of state<>. Chris@16: // To correct this, derive from state<> instead of simple_state<>. Chris@16: BOOST_ASSERT( get_pointer( pContext_ ) != 0 ); Chris@16: return pContext_->outermost_context(); Chris@16: } Chris@16: Chris@16: template< class OtherContext > Chris@16: OtherContext & context() Chris@16: { Chris@16: typedef typename mpl::if_< Chris@16: is_base_of< OtherContext, MostDerived >, Chris@16: context_impl_this_context, Chris@16: context_impl_other_context Chris@16: >::type impl; Chris@16: return impl::template context_impl< OtherContext >( *this ); Chris@16: } Chris@16: Chris@16: template< class OtherContext > Chris@16: const OtherContext & context() const Chris@16: { Chris@16: typedef typename mpl::if_< Chris@16: is_base_of< OtherContext, MostDerived >, Chris@16: context_impl_this_context, Chris@16: context_impl_other_context Chris@16: >::type impl; Chris@16: return impl::template context_impl< OtherContext >( *this ); Chris@16: } Chris@16: Chris@16: template< class Target > Chris@16: Target state_cast() const Chris@16: { Chris@16: return outermost_context_base().template state_cast< Target >(); Chris@16: } Chris@16: Chris@16: template< class Target > Chris@16: Target state_downcast() const Chris@16: { Chris@16: return outermost_context_base().template state_downcast< Target >(); Chris@16: } Chris@16: Chris@16: typedef typename context_type::state_base_type state_base_type; Chris@16: typedef typename context_type::state_iterator state_iterator; Chris@16: Chris@16: state_iterator state_begin() const Chris@16: { Chris@16: return outermost_context_base().state_begin(); Chris@16: } Chris@16: Chris@16: state_iterator state_end() const Chris@16: { Chris@16: return outermost_context_base().state_end(); Chris@16: } Chris@16: Chris@16: Chris@16: typedef typename context_type::event_base_ptr_type event_base_ptr_type; Chris@16: Chris@16: void post_event( const event_base_ptr_type & pEvent ) Chris@16: { Chris@16: outermost_context_base().post_event_impl( pEvent ); Chris@16: } Chris@16: Chris@16: void post_event( const event_base & evt ) Chris@16: { Chris@16: outermost_context_base().post_event_impl( evt ); Chris@16: } Chris@16: Chris@16: result discard_event() Chris@16: { Chris@16: return detail::result_utility::make_result( detail::do_discard_event ); Chris@16: } Chris@16: Chris@16: result forward_event() Chris@16: { Chris@16: return detail::result_utility::make_result( detail::do_forward_event ); Chris@16: } Chris@16: Chris@16: result defer_event() Chris@16: { Chris@16: this->state_base_type::defer_event(); Chris@16: return detail::result_utility::make_result( detail::do_defer_event ); Chris@16: } Chris@16: Chris@16: template< class DestinationState > Chris@16: result transit() Chris@16: { Chris@16: return transit_impl< DestinationState, outermost_context_type >( Chris@16: detail::no_transition_function() ); Chris@16: } Chris@16: Chris@16: template< class DestinationState, class TransitionContext, class Event > Chris@16: result transit( Chris@16: void ( TransitionContext::*pTransitionAction )( const Event & ), Chris@16: const Event & evt ) Chris@16: { Chris@16: return transit_impl< DestinationState, TransitionContext >( Chris@16: detail::transition_function< TransitionContext, Event >( Chris@16: pTransitionAction, evt ) ); Chris@16: } Chris@16: Chris@16: result terminate() Chris@16: { Chris@16: outermost_context_base().terminate_as_reaction( *this ); Chris@16: return detail::result_utility::make_result( detail::do_discard_event ); Chris@16: } Chris@16: Chris@16: template< Chris@16: class HistoryContext, Chris@16: detail::orthogonal_position_type orthogonalPosition > Chris@16: void clear_shallow_history() Chris@16: { Chris@16: outermost_context_base().template clear_shallow_history< Chris@16: HistoryContext, orthogonalPosition >(); Chris@16: } Chris@16: Chris@16: template< Chris@16: class HistoryContext, Chris@16: detail::orthogonal_position_type orthogonalPosition > Chris@16: void clear_deep_history() Chris@16: { Chris@16: outermost_context_base().template clear_deep_history< Chris@16: HistoryContext, orthogonalPosition >(); Chris@16: } Chris@16: Chris@16: const event_base * triggering_event() const Chris@16: { Chris@16: return outermost_context_base().triggering_event(); Chris@16: } Chris@16: Chris@16: protected: Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: simple_state() : pContext_( 0 ) {} Chris@16: Chris@16: ~simple_state() Chris@16: { Chris@16: // As a result of a throwing derived class constructor, this destructor Chris@16: // can be called before the context is set. Chris@16: if ( get_pointer( pContext_ ) != 0 ) Chris@16: { Chris@16: if ( this->deferred_events() ) Chris@16: { Chris@16: outermost_context_base().release_events(); Chris@16: } Chris@16: Chris@16: pContext_->remove_inner_state( orthogonal_position::value ); Chris@16: } Chris@16: } Chris@16: Chris@16: public: Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: // The following declarations should be private. Chris@16: // They are only public because many compilers lack template friends. Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: typedef typename Context::inner_orthogonal_position orthogonal_position; Chris@16: Chris@16: // If you receive a Chris@16: // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE'" or similar Chris@16: // compiler error here then either this state resides in a non-existent Chris@16: // orthogonal region of the outer state or the outer state does not have Chris@16: // inner states. Chris@16: BOOST_STATIC_ASSERT( ( mpl::less< Chris@16: orthogonal_position, Chris@16: typename context_type::no_of_orthogonal_regions >::value ) ); Chris@16: Chris@16: typedef MostDerived inner_context_type; Chris@16: typedef mpl::integral_c< detail::orthogonal_position_type, 0 > Chris@16: inner_orthogonal_position; Chris@16: Chris@16: typedef typename context_type::event_base_type event_base_type; Chris@16: typedef typename context_type::rtti_policy_type rtti_policy_type; Chris@16: Chris@16: typedef typename context_type::outermost_context_base_type Chris@16: outermost_context_base_type; Chris@16: typedef typename context_type::inner_context_ptr_type context_ptr_type; Chris@16: typedef typename context_type::state_list_type state_list_type; Chris@16: typedef intrusive_ptr< inner_context_type > inner_context_ptr_type; Chris@16: typedef typename detail::make_list< InnerInitial >::type Chris@16: inner_initial_list; Chris@16: typedef typename mpl::size< inner_initial_list >::type Chris@16: inner_initial_list_size; Chris@16: typedef mpl::integral_c< Chris@16: detail::orthogonal_position_type, Chris@16: inner_initial_list_size::value > no_of_orthogonal_regions; Chris@16: typedef typename mpl::push_front< Chris@16: typename context_type::context_type_list, Chris@16: context_type >::type context_type_list; Chris@16: Chris@16: // If you receive a Chris@16: // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE'" or similar Chris@16: // compiler error here then the direct or indirect context of this state Chris@16: // has deep history _and_ this state has two or more orthogonal regions. Chris@16: // Boost.Statechart does not currently support deep history in a state whose Chris@16: // direct or indirect inner states have two or more orthogonal regions. Chris@16: // Please consult the documentation on how to work around this limitation. Chris@16: BOOST_STATIC_ASSERT( ( mpl::or_< Chris@16: mpl::less< Chris@16: no_of_orthogonal_regions, Chris@16: mpl::integral_c< detail::orthogonal_position_type, 2 > >, Chris@16: mpl::not_< Chris@16: typename context_type::inherited_deep_history > >::value ) ); Chris@16: Chris@16: typedef mpl::bool_< ( historyMode & has_shallow_history ) != 0 > Chris@16: shallow_history; Chris@16: typedef typename context_type::shallow_history stores_shallow_history; Chris@16: Chris@16: typedef mpl::bool_< ( historyMode & has_deep_history ) != 0 > Chris@16: deep_history; Chris@16: typedef typename mpl::or_< Chris@16: deep_history, Chris@16: typename context_type::inherited_deep_history Chris@16: >::type inherited_deep_history; Chris@16: typedef typename mpl::and_< Chris@16: inherited_deep_history, Chris@16: mpl::empty< inner_initial_list > >::type stores_deep_history; Chris@16: Chris@16: void * operator new( std::size_t size ) Chris@16: { Chris@16: return detail::allocate< MostDerived, Chris@16: typename outermost_context_type::allocator_type >( size ); Chris@16: } Chris@16: Chris@16: void operator delete( void * pState ) Chris@16: { Chris@16: detail::deallocate< MostDerived, Chris@16: typename outermost_context_type::allocator_type >( pState ); Chris@16: } Chris@16: Chris@16: outermost_context_base_type & outermost_context_base() Chris@16: { Chris@16: // This assert fails when an attempt is made to access the state machine Chris@16: // from a constructor of a state that is *not* a subtype of state<>. Chris@16: // To correct this, derive from state<> instead of simple_state<>. Chris@16: BOOST_ASSERT( get_pointer( pContext_ ) != 0 ); Chris@16: return pContext_->outermost_context_base(); Chris@16: } Chris@16: Chris@16: const outermost_context_base_type & outermost_context_base() const Chris@16: { Chris@16: // This assert fails when an attempt is made to access the state machine Chris@16: // from a constructor of a state that is *not* a subtype of state<>. Chris@16: // To correct this, derive from state<> instead of simple_state<>. Chris@16: BOOST_ASSERT( get_pointer( pContext_ ) != 0 ); Chris@16: return pContext_->outermost_context_base(); Chris@16: } Chris@16: Chris@16: virtual const state_base_type * outer_state_ptr() const Chris@16: { Chris@16: typedef typename mpl::if_< Chris@16: is_same< outermost_context_type, context_type >, Chris@16: outer_state_ptr_impl_outermost, Chris@16: outer_state_ptr_impl_non_outermost Chris@16: >::type impl; Chris@16: return impl::outer_state_ptr_impl( *this ); Chris@16: } Chris@16: Chris@16: virtual detail::reaction_result react_impl( Chris@16: const event_base_type & evt, Chris@16: typename rtti_policy_type::id_type eventType ) Chris@16: { Chris@16: typedef typename detail::make_list< Chris@16: typename MostDerived::reactions >::type reaction_list; Chris@16: detail::reaction_result reactionResult = Chris@16: local_react< reaction_list >( evt, eventType ); Chris@16: Chris@16: // At this point we can only safely access pContext_ if the handler did Chris@16: // not return do_discard_event! Chris@16: if ( reactionResult == detail::do_forward_event ) Chris@16: { Chris@16: // TODO: The following call to react_impl of our outer state should Chris@16: // be made with a context_type:: prefix to call directly instead of Chris@16: // virtually. For some reason the compiler complains... Chris@16: reactionResult = pContext_->react_impl( evt, eventType ); Chris@16: } Chris@16: Chris@16: return reactionResult; Chris@16: } Chris@16: Chris@16: virtual void exit_impl( Chris@16: typename base_type::direct_state_base_ptr_type & pSelf, Chris@16: typename state_base_type::node_state_base_ptr_type & Chris@16: pOutermostUnstableState, Chris@16: bool performFullExit ) Chris@16: { Chris@16: inner_context_ptr_type pMostDerivedSelf = Chris@16: polymorphic_downcast< MostDerived * >( this ); Chris@16: pSelf = 0; Chris@16: exit_impl( pMostDerivedSelf, pOutermostUnstableState, performFullExit ); Chris@16: } Chris@16: Chris@16: void exit_impl( Chris@16: inner_context_ptr_type & pSelf, Chris@16: typename state_base_type::node_state_base_ptr_type & Chris@16: pOutermostUnstableState, Chris@16: bool performFullExit ) Chris@16: { Chris@16: switch ( this->ref_count() ) Chris@16: { Chris@16: case 2: Chris@16: if ( get_pointer( pOutermostUnstableState ) == Chris@16: static_cast< state_base_type * >( this ) ) Chris@16: { Chris@16: pContext_->set_outermost_unstable_state( Chris@16: pOutermostUnstableState ); Chris@101: BOOST_FALLTHROUGH; Chris@16: } Chris@16: else Chris@16: { Chris@16: break; Chris@16: } Chris@16: case 1: Chris@16: { Chris@16: if ( get_pointer( pOutermostUnstableState ) == 0 ) Chris@16: { Chris@16: pContext_->set_outermost_unstable_state( Chris@16: pOutermostUnstableState ); Chris@16: } Chris@16: Chris@16: if ( performFullExit ) Chris@16: { Chris@16: pSelf->exit(); Chris@16: check_store_shallow_history< stores_shallow_history >(); Chris@16: check_store_deep_history< stores_deep_history >(); Chris@16: } Chris@16: Chris@16: context_ptr_type pContext = pContext_; Chris@16: pSelf = 0; Chris@16: pContext->exit_impl( Chris@16: pContext, pOutermostUnstableState, performFullExit ); Chris@16: break; Chris@16: } Chris@16: default: Chris@16: break; Chris@16: } Chris@16: } Chris@16: Chris@16: void set_outermost_unstable_state( Chris@16: typename state_base_type::node_state_base_ptr_type & Chris@16: pOutermostUnstableState ) Chris@16: { Chris@16: pOutermostUnstableState = this; Chris@16: } Chris@16: Chris@16: template< class OtherContext > Chris@16: const typename OtherContext::inner_context_ptr_type & context_ptr() const Chris@16: { Chris@16: typedef typename mpl::if_< Chris@16: is_same< OtherContext, context_type >, Chris@16: context_ptr_impl_my_context, Chris@16: context_ptr_impl_other_context Chris@16: >::type impl; Chris@16: Chris@16: return impl::template context_ptr_impl< OtherContext >( *this ); Chris@16: } Chris@16: Chris@16: static void initial_deep_construct( Chris@16: outermost_context_base_type & outermostContextBase ) Chris@16: { Chris@16: deep_construct( &outermostContextBase, outermostContextBase ); Chris@16: } Chris@16: Chris@16: static void deep_construct( Chris@16: const context_ptr_type & pContext, Chris@16: outermost_context_base_type & outermostContextBase ) Chris@16: { Chris@16: const inner_context_ptr_type pInnerContext( Chris@16: shallow_construct( pContext, outermostContextBase ) ); Chris@16: deep_construct_inner< inner_initial_list >( Chris@16: pInnerContext, outermostContextBase ); Chris@16: } Chris@16: Chris@16: static inner_context_ptr_type shallow_construct( Chris@16: const context_ptr_type & pContext, Chris@16: outermost_context_base_type & outermostContextBase ) Chris@16: { Chris@16: const inner_context_ptr_type pInnerContext( new MostDerived ); Chris@16: pInnerContext->set_context( pContext ); Chris@16: outermostContextBase.add( pInnerContext ); Chris@16: return pInnerContext; Chris@16: } Chris@16: Chris@16: void set_context( const context_ptr_type & pContext ) Chris@16: { Chris@16: BOOST_ASSERT( get_pointer( pContext ) != 0 ); Chris@16: pContext_ = pContext; Chris@16: base_type::set_context( Chris@16: orthogonal_position::value, get_pointer( pContext ) ); Chris@16: } Chris@16: Chris@16: template< class InnerList > Chris@16: static void deep_construct_inner( Chris@16: const inner_context_ptr_type & pInnerContext, Chris@16: outermost_context_base_type & outermostContextBase ) Chris@16: { Chris@16: typedef typename mpl::if_< Chris@16: mpl::empty< InnerList >, Chris@16: deep_construct_inner_impl_empty, Chris@16: deep_construct_inner_impl_non_empty Chris@16: >::type impl; Chris@16: impl::template deep_construct_inner_impl< InnerList >( Chris@16: pInnerContext, outermostContextBase ); Chris@16: } Chris@16: Chris@16: template< class LeafState > Chris@16: void store_deep_history_impl() Chris@16: { Chris@16: detail::deep_history_storer< Chris@16: context_type::inherited_deep_history::value, Chris@16: context_type::deep_history::value Chris@16: >::template store_deep_history< MostDerived, LeafState >( Chris@16: *pContext_ ); Chris@16: } Chris@16: Chris@16: private: Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: struct context_ptr_impl_other_context Chris@16: { Chris@16: template< class OtherContext, class State > Chris@16: static const typename OtherContext::inner_context_ptr_type & Chris@16: context_ptr_impl( const State & stt ) Chris@16: { Chris@16: // This assert fails when an attempt is made to access an outer Chris@16: // context from a constructor of a state that is *not* a subtype of Chris@16: // state<>. To correct this, derive from state<> instead of Chris@16: // simple_state<>. Chris@16: BOOST_ASSERT( get_pointer( stt.pContext_ ) != 0 ); Chris@16: return stt.pContext_->template context_ptr< OtherContext >(); Chris@16: } Chris@16: }; Chris@16: friend struct context_ptr_impl_other_context; Chris@16: Chris@16: struct context_ptr_impl_my_context Chris@16: { Chris@16: template< class OtherContext, class State > Chris@16: static const typename OtherContext::inner_context_ptr_type & Chris@16: context_ptr_impl( const State & stt ) Chris@16: { Chris@16: // This assert fails when an attempt is made to access an outer Chris@16: // context from a constructor of a state that is *not* a subtype of Chris@16: // state<>. To correct this, derive from state<> instead of Chris@16: // simple_state<>. Chris@16: BOOST_ASSERT( get_pointer( stt.pContext_ ) != 0 ); Chris@16: return stt.pContext_; Chris@16: } Chris@16: }; Chris@16: friend struct context_ptr_impl_my_context; Chris@16: Chris@16: struct context_impl_other_context Chris@16: { Chris@16: template< class OtherContext, class State > Chris@16: static OtherContext & context_impl( State & stt ) Chris@16: { Chris@16: // This assert fails when an attempt is made to access an outer Chris@16: // context from a constructor of a state that is *not* a subtype of Chris@16: // state<>. To correct this, derive from state<> instead of Chris@16: // simple_state<>. Chris@16: BOOST_ASSERT( get_pointer( stt.pContext_ ) != 0 ); Chris@16: return stt.pContext_->template context< OtherContext >(); Chris@16: } Chris@16: }; Chris@16: friend struct context_impl_other_context; Chris@16: Chris@16: struct context_impl_this_context Chris@16: { Chris@16: template< class OtherContext, class State > Chris@16: static OtherContext & context_impl( State & stt ) Chris@16: { Chris@16: return *polymorphic_downcast< MostDerived * >( &stt ); Chris@16: } Chris@16: }; Chris@16: friend struct context_impl_this_context; Chris@16: Chris@16: template< class DestinationState, Chris@16: class TransitionContext, Chris@16: class TransitionAction > Chris@16: result transit_impl( const TransitionAction & transitionAction ) Chris@16: { Chris@16: typedef typename mpl::find_if< Chris@16: context_type_list, Chris@16: mpl::contains< Chris@16: typename DestinationState::context_type_list, Chris@16: mpl::placeholders::_ > >::type common_context_iter; Chris@16: typedef typename mpl::deref< common_context_iter >::type Chris@16: common_context_type; Chris@16: typedef typename mpl::distance< Chris@16: typename mpl::begin< context_type_list >::type, Chris@16: common_context_iter >::type termination_state_position; Chris@16: typedef typename mpl::push_front< context_type_list, MostDerived >::type Chris@16: possible_transition_contexts; Chris@16: typedef typename mpl::at< Chris@16: possible_transition_contexts, Chris@16: termination_state_position >::type termination_state_type; Chris@16: Chris@16: termination_state_type & terminationState( Chris@16: context< termination_state_type >() ); Chris@16: const typename Chris@16: common_context_type::inner_context_ptr_type pCommonContext( Chris@16: terminationState.template context_ptr< common_context_type >() ); Chris@16: outermost_context_base_type & outermostContextBase( Chris@16: pCommonContext->outermost_context_base() ); Chris@16: Chris@16: #ifdef BOOST_STATECHART_RELAX_TRANSITION_CONTEXT Chris@16: typedef typename mpl::distance< Chris@16: typename mpl::begin< possible_transition_contexts >::type, Chris@16: typename mpl::find< Chris@16: possible_transition_contexts, TransitionContext >::type Chris@16: >::type proposed_transition_context_position; Chris@16: Chris@16: typedef typename mpl::plus< Chris@16: termination_state_position, Chris@16: mpl::long_< 1 > Chris@16: >::type uml_transition_context_position; Chris@16: Chris@16: typedef typename mpl::deref< typename mpl::max_element< Chris@16: mpl::list< Chris@16: proposed_transition_context_position, Chris@16: uml_transition_context_position >, Chris@16: mpl::greater< mpl::placeholders::_, mpl::placeholders::_ > Chris@16: >::type >::type real_transition_context_position; Chris@16: Chris@16: typedef typename mpl::at< Chris@16: possible_transition_contexts, Chris@16: real_transition_context_position >::type real_transition_context_type; Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning( push ) Chris@16: # pragma warning( disable: 4127 ) // conditional expression is constant Chris@16: #endif Chris@16: if ( ( proposed_transition_context_position::value == 0 ) && Chris@16: ( inner_initial_list_size::value == 0 ) ) Chris@16: { Chris@16: transitionAction( *polymorphic_downcast< MostDerived * >( this ) ); Chris@16: outermostContextBase.terminate_as_part_of_transit( terminationState ); Chris@16: } Chris@16: else if ( proposed_transition_context_position::value >= Chris@16: uml_transition_context_position::value ) Chris@16: { Chris@16: real_transition_context_type & transitionContext = Chris@16: context< real_transition_context_type >(); Chris@16: outermostContextBase.terminate_as_part_of_transit( terminationState ); Chris@16: transitionAction( transitionContext ); Chris@16: } Chris@16: else Chris@16: { Chris@16: typename real_transition_context_type::inner_context_ptr_type Chris@16: pTransitionContext = context_ptr< real_transition_context_type >(); Chris@16: outermostContextBase.terminate_as_part_of_transit( Chris@16: *pTransitionContext ); Chris@16: transitionAction( *pTransitionContext ); Chris@16: pTransitionContext = 0; Chris@16: outermostContextBase.terminate_as_part_of_transit( terminationState ); Chris@16: } Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning( pop ) Chris@16: #endif Chris@16: #else Chris@16: outermostContextBase.terminate_as_part_of_transit( terminationState ); Chris@16: transitionAction( *pCommonContext ); Chris@16: #endif Chris@16: Chris@16: typedef typename detail::make_context_list< Chris@16: common_context_type, DestinationState >::type context_list_type; Chris@16: Chris@16: // If you receive a Chris@16: // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE'" or Chris@16: // similar compiler error here then you tried to make an invalid Chris@16: // transition between different orthogonal regions. Chris@16: BOOST_STATIC_ASSERT( ( mpl::equal_to< Chris@16: typename termination_state_type::orthogonal_position, Chris@16: typename mpl::front< context_list_type >::type::orthogonal_position Chris@16: >::value ) ); Chris@16: Chris@16: detail::constructor< Chris@16: context_list_type, outermost_context_base_type >::construct( Chris@16: pCommonContext, outermostContextBase ); Chris@16: Chris@16: return detail::result_utility::make_result( detail::do_discard_event ); Chris@16: } Chris@16: Chris@16: struct local_react_impl_non_empty Chris@16: { Chris@16: template< class ReactionList, class State > Chris@16: static detail::reaction_result local_react_impl( Chris@16: State & stt, Chris@16: const event_base_type & evt, Chris@16: typename rtti_policy_type::id_type eventType ) Chris@16: { Chris@16: detail::reaction_result reactionResult = Chris@16: mpl::front< ReactionList >::type::react( Chris@16: *polymorphic_downcast< MostDerived * >( &stt ), Chris@16: evt, eventType ); Chris@16: Chris@16: if ( reactionResult == detail::no_reaction ) Chris@16: { Chris@16: reactionResult = stt.template local_react< Chris@16: typename mpl::pop_front< ReactionList >::type >( Chris@16: evt, eventType ); Chris@16: } Chris@16: Chris@16: return reactionResult; Chris@16: } Chris@16: }; Chris@16: friend struct local_react_impl_non_empty; Chris@16: Chris@16: struct local_react_impl_empty Chris@16: { Chris@16: template< class ReactionList, class State > Chris@16: static detail::reaction_result local_react_impl( Chris@16: State &, const event_base_type &, typename rtti_policy_type::id_type ) Chris@16: { Chris@16: return detail::do_forward_event; Chris@16: } Chris@16: }; Chris@16: Chris@16: template< class ReactionList > Chris@16: detail::reaction_result local_react( Chris@16: const event_base_type & evt, Chris@16: typename rtti_policy_type::id_type eventType ) Chris@16: { Chris@16: typedef typename mpl::if_< Chris@16: mpl::empty< ReactionList >, Chris@16: local_react_impl_empty, Chris@16: local_react_impl_non_empty Chris@16: >::type impl; Chris@16: return impl::template local_react_impl< ReactionList >( Chris@16: *this, evt, eventType ); Chris@16: } Chris@16: Chris@16: struct outer_state_ptr_impl_non_outermost Chris@16: { Chris@16: template< class State > Chris@16: static const state_base_type * outer_state_ptr_impl( const State & stt ) Chris@16: { Chris@16: return get_pointer( stt.pContext_ ); Chris@16: } Chris@16: }; Chris@16: friend struct outer_state_ptr_impl_non_outermost; Chris@16: Chris@16: struct outer_state_ptr_impl_outermost Chris@16: { Chris@16: template< class State > Chris@16: static const state_base_type * outer_state_ptr_impl( const State & ) Chris@16: { Chris@16: return 0; Chris@16: } Chris@16: }; Chris@16: Chris@16: struct deep_construct_inner_impl_non_empty Chris@16: { Chris@16: template< class InnerList > Chris@16: static void deep_construct_inner_impl( Chris@16: const inner_context_ptr_type & pInnerContext, Chris@16: outermost_context_base_type & outermostContextBase ) Chris@16: { Chris@16: typedef typename mpl::front< InnerList >::type current_inner; Chris@16: Chris@16: // If you receive a Chris@16: // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE'" or Chris@16: // similar compiler error here then there is a mismatch between the Chris@16: // orthogonal position of a state and its position in the inner Chris@16: // initial list of its outer state. Chris@16: BOOST_STATIC_ASSERT( ( is_same< Chris@16: current_inner, Chris@16: typename mpl::at< Chris@16: typename current_inner::context_type::inner_initial_list, Chris@16: typename current_inner::orthogonal_position >::type >::value ) ); Chris@16: Chris@16: current_inner::deep_construct( pInnerContext, outermostContextBase ); Chris@16: deep_construct_inner< typename mpl::pop_front< InnerList >::type >( Chris@16: pInnerContext, outermostContextBase ); Chris@16: } Chris@16: }; Chris@16: Chris@16: struct deep_construct_inner_impl_empty Chris@16: { Chris@16: template< class InnerList > Chris@16: static void deep_construct_inner_impl( Chris@16: const inner_context_ptr_type &, outermost_context_base_type & ) {} Chris@16: }; Chris@16: Chris@16: struct check_store_shallow_history_impl_no Chris@16: { Chris@16: template< class State > Chris@16: static void check_store_shallow_history_impl( State & ) {} Chris@16: }; Chris@16: Chris@16: struct check_store_shallow_history_impl_yes Chris@16: { Chris@16: template< class State > Chris@16: static void check_store_shallow_history_impl( State & stt ) Chris@16: { Chris@16: stt.outermost_context_base().template store_shallow_history< Chris@16: MostDerived >(); Chris@16: } Chris@16: }; Chris@16: friend struct check_store_shallow_history_impl_yes; Chris@16: Chris@16: template< class StoreShallowHistory > Chris@16: void check_store_shallow_history() Chris@16: { Chris@16: typedef typename mpl::if_< Chris@16: StoreShallowHistory, Chris@16: check_store_shallow_history_impl_yes, Chris@16: check_store_shallow_history_impl_no Chris@16: >::type impl; Chris@16: impl::check_store_shallow_history_impl( *this ); Chris@16: } Chris@16: Chris@16: struct check_store_deep_history_impl_no Chris@16: { Chris@16: template< class State > Chris@16: static void check_store_deep_history_impl( State & ) {} Chris@16: }; Chris@16: Chris@16: struct check_store_deep_history_impl_yes Chris@16: { Chris@16: template< class State > Chris@16: static void check_store_deep_history_impl( State & stt ) Chris@16: { Chris@16: stt.template store_deep_history_impl< MostDerived >(); Chris@16: } Chris@16: }; Chris@16: friend struct check_store_deep_history_impl_yes; Chris@16: Chris@16: template< class StoreDeepHistory > Chris@16: void check_store_deep_history() Chris@16: { Chris@16: typedef typename mpl::if_< Chris@16: StoreDeepHistory, Chris@16: check_store_deep_history_impl_yes, Chris@16: check_store_deep_history_impl_no Chris@16: >::type impl; Chris@16: impl::check_store_deep_history_impl( *this ); Chris@16: } Chris@16: Chris@16: Chris@16: context_ptr_type pContext_; Chris@16: }; Chris@16: Chris@16: Chris@16: Chris@16: #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP Chris@16: } // namespace statechart Chris@16: #endif Chris@16: Chris@16: Chris@16: Chris@16: template< class MostDerived, class Context, Chris@16: class InnerInitial, history_mode historyMode > Chris@16: inline void intrusive_ptr_release( const ::boost::statechart::simple_state< Chris@16: MostDerived, Context, InnerInitial, historyMode > * pBase ) Chris@16: { Chris@16: if ( pBase->release() ) Chris@16: { Chris@16: // The cast is necessary because the simple_state destructor is non- Chris@16: // virtual (and inaccessible from this context) Chris@16: delete polymorphic_downcast< const MostDerived * >( pBase ); Chris@16: } Chris@16: } Chris@16: Chris@16: Chris@16: Chris@16: #ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP Chris@16: } // namespace statechart Chris@16: #endif Chris@16: Chris@16: Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: Chris@16: Chris@16: #endif