#ifndef BOOST_STATECHART_DETAIL_NODE_STATE_HPP_INCLUDED #define BOOST_STATECHART_DETAIL_NODE_STATE_HPP_INCLUDED ////////////////////////////////////////////////////////////////////////////// // Copyright 2002-2006 Andreas Huber Doenni // Distributed under the Boost Software License, Version 1.0. (See accompany- // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ////////////////////////////////////////////////////////////////////////////// #include #include #include // BOOST_ASSERT #include // std::find_if namespace boost { namespace statechart { namespace detail { template< class Allocator, class RttiPolicy > class node_state_base : public state_base< Allocator, RttiPolicy > { typedef state_base< Allocator, RttiPolicy > base_type; protected: ////////////////////////////////////////////////////////////////////////// node_state_base( typename RttiPolicy::id_provider_type idProvider ) : base_type( idProvider ) { } ~node_state_base() {} public: ////////////////////////////////////////////////////////////////////////// // The following declarations should be private. // They are only public because many compilers lack template friends. ////////////////////////////////////////////////////////////////////////// typedef base_type state_base_type; typedef intrusive_ptr< node_state_base > direct_state_base_ptr_type; virtual void exit_impl( direct_state_base_ptr_type & pSelf, typename base_type::node_state_base_ptr_type & pOutermostUnstableState, bool performFullExit ) = 0; }; ////////////////////////////////////////////////////////////////////////////// template< class OrthogonalRegionCount, class Allocator, class RttiPolicy > class node_state : public node_state_base< Allocator, RttiPolicy > { typedef node_state_base< Allocator, RttiPolicy > base_type; protected: ////////////////////////////////////////////////////////////////////////// node_state( typename RttiPolicy::id_provider_type idProvider ) : base_type( idProvider ) { for ( orthogonal_position_type pos = 0; pos < OrthogonalRegionCount::value; ++pos ) { pInnerStates[ pos ] = 0; } } ~node_state() {} public: ////////////////////////////////////////////////////////////////////////// // The following declarations should be private. // They are only public because many compilers lack template friends. ////////////////////////////////////////////////////////////////////////// typedef typename base_type::state_base_type state_base_type; void add_inner_state( orthogonal_position_type position, state_base_type * pInnerState ) { BOOST_ASSERT( ( position < OrthogonalRegionCount::value ) && ( pInnerStates[ position ] == 0 ) ); pInnerStates[ position ] = pInnerState; } void remove_inner_state( orthogonal_position_type position ) { BOOST_ASSERT( position < OrthogonalRegionCount::value ); pInnerStates[ position ] = 0; } virtual void remove_from_state_list( typename state_base_type::state_list_type::iterator & statesEnd, typename state_base_type::node_state_base_ptr_type & pOutermostUnstableState, bool performFullExit ) { state_base_type ** const pPastEnd = &pInnerStates[ OrthogonalRegionCount::value ]; // We must not iterate past the last inner state because *this* state // will no longer exist when the last inner state has been removed state_base_type ** const pFirstNonNull = std::find_if( &pInnerStates[ 0 ], pPastEnd, &node_state::is_not_null ); if ( pFirstNonNull == pPastEnd ) { // The state does not have inner states but is still alive, this must // be the outermost unstable state then. BOOST_ASSERT( get_pointer( pOutermostUnstableState ) == this ); typename state_base_type::node_state_base_ptr_type pSelf = pOutermostUnstableState; pSelf->exit_impl( pSelf, pOutermostUnstableState, performFullExit ); } else { // Destroy inner states in the reverse order of construction for ( state_base_type ** pState = pPastEnd; pState != pFirstNonNull; ) { --pState; // An inner orthogonal state might have been terminated long before, // that's why we have to check for 0 pointers if ( *pState != 0 ) { ( *pState )->remove_from_state_list( statesEnd, pOutermostUnstableState, performFullExit ); } } } } typedef typename base_type::direct_state_base_ptr_type direct_state_base_ptr_type; private: ////////////////////////////////////////////////////////////////////////// static bool is_not_null( const state_base_type * pInner ) { return pInner != 0; } state_base_type * pInnerStates[ OrthogonalRegionCount::value ]; }; } // namespace detail } // namespace statechart } // namespace boost #endif