Chris@16: #ifndef BOOST_STATECHART_DETAIL_NODE_STATE_HPP_INCLUDED Chris@16: #define BOOST_STATECHART_DETAIL_NODE_STATE_HPP_INCLUDED Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Copyright 2002-2006 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 // BOOST_ASSERT Chris@16: Chris@16: #include // std::find_if 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: template< class Allocator, class RttiPolicy > Chris@16: class node_state_base : public state_base< Allocator, RttiPolicy > Chris@16: { Chris@16: typedef state_base< Allocator, RttiPolicy > base_type; Chris@16: protected: Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: node_state_base( typename RttiPolicy::id_provider_type idProvider ) : Chris@16: base_type( idProvider ) Chris@16: { Chris@16: } Chris@16: Chris@16: ~node_state_base() {} 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 base_type state_base_type; Chris@16: typedef intrusive_ptr< node_state_base > direct_state_base_ptr_type; Chris@16: virtual void exit_impl( Chris@16: direct_state_base_ptr_type & pSelf, Chris@16: typename base_type::node_state_base_ptr_type & pOutermostUnstableState, Chris@16: bool performFullExit ) = 0; Chris@16: }; Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: template< class OrthogonalRegionCount, class Allocator, class RttiPolicy > Chris@16: class node_state : public node_state_base< Allocator, RttiPolicy > Chris@16: { Chris@16: typedef node_state_base< Allocator, RttiPolicy > base_type; Chris@16: protected: Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: node_state( typename RttiPolicy::id_provider_type idProvider ) : Chris@16: base_type( idProvider ) Chris@16: { Chris@16: for ( orthogonal_position_type pos = 0; Chris@16: pos < OrthogonalRegionCount::value; ++pos ) Chris@16: { Chris@16: pInnerStates[ pos ] = 0; Chris@16: } Chris@16: } Chris@16: Chris@16: ~node_state() {} 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 base_type::state_base_type state_base_type; Chris@16: Chris@16: void add_inner_state( orthogonal_position_type position, Chris@16: state_base_type * pInnerState ) Chris@16: { Chris@16: BOOST_ASSERT( ( position < OrthogonalRegionCount::value ) && Chris@16: ( pInnerStates[ position ] == 0 ) ); Chris@16: pInnerStates[ position ] = pInnerState; Chris@16: } Chris@16: Chris@16: void remove_inner_state( orthogonal_position_type position ) Chris@16: { Chris@16: BOOST_ASSERT( position < OrthogonalRegionCount::value ); Chris@16: pInnerStates[ position ] = 0; Chris@16: } Chris@16: Chris@16: virtual void remove_from_state_list( Chris@16: typename state_base_type::state_list_type::iterator & statesEnd, Chris@16: typename state_base_type::node_state_base_ptr_type & Chris@16: pOutermostUnstableState, Chris@16: bool performFullExit ) Chris@16: { Chris@16: state_base_type ** const pPastEnd = Chris@16: &pInnerStates[ OrthogonalRegionCount::value ]; Chris@16: // We must not iterate past the last inner state because *this* state Chris@16: // will no longer exist when the last inner state has been removed Chris@16: state_base_type ** const pFirstNonNull = std::find_if( Chris@16: &pInnerStates[ 0 ], pPastEnd, &node_state::is_not_null ); Chris@16: Chris@16: if ( pFirstNonNull == pPastEnd ) Chris@16: { Chris@16: // The state does not have inner states but is still alive, this must Chris@16: // be the outermost unstable state then. Chris@16: BOOST_ASSERT( get_pointer( pOutermostUnstableState ) == this ); Chris@16: typename state_base_type::node_state_base_ptr_type pSelf = Chris@16: pOutermostUnstableState; Chris@16: pSelf->exit_impl( pSelf, pOutermostUnstableState, performFullExit ); Chris@16: } Chris@16: else Chris@16: { Chris@16: // Destroy inner states in the reverse order of construction Chris@16: for ( state_base_type ** pState = pPastEnd; pState != pFirstNonNull; ) Chris@16: { Chris@16: --pState; Chris@16: Chris@16: // An inner orthogonal state might have been terminated long before, Chris@16: // that's why we have to check for 0 pointers Chris@16: if ( *pState != 0 ) Chris@16: { Chris@16: ( *pState )->remove_from_state_list( Chris@16: statesEnd, pOutermostUnstableState, performFullExit ); Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: typedef typename base_type::direct_state_base_ptr_type Chris@16: direct_state_base_ptr_type; Chris@16: Chris@16: private: Chris@16: ////////////////////////////////////////////////////////////////////////// Chris@16: static bool is_not_null( const state_base_type * pInner ) Chris@16: { Chris@16: return pInner != 0; Chris@16: } Chris@16: Chris@16: state_base_type * pInnerStates[ OrthogonalRegionCount::value ]; Chris@16: }; Chris@16: Chris@16: Chris@16: Chris@16: } // namespace detail Chris@16: } // namespace statechart Chris@16: } // namespace boost Chris@16: Chris@16: Chris@16: Chris@16: #endif