Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:52:31

0001 #ifndef BOOST_STATECHART_DETAIL_NODE_STATE_HPP_INCLUDED
0002 #define BOOST_STATECHART_DETAIL_NODE_STATE_HPP_INCLUDED
0003 //////////////////////////////////////////////////////////////////////////////
0004 // Copyright 2002-2006 Andreas Huber Doenni
0005 // Distributed under the Boost Software License, Version 1.0. (See accompany-
0006 // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 //////////////////////////////////////////////////////////////////////////////
0008 
0009 
0010 
0011 #include <boost/statechart/detail/state_base.hpp>
0012 
0013 #include <boost/intrusive_ptr.hpp>
0014 #include <boost/assert.hpp>  // BOOST_ASSERT
0015 
0016 #include <algorithm> // std::find_if
0017 
0018 
0019 
0020 namespace boost
0021 {
0022 namespace statechart
0023 {
0024 namespace detail
0025 {
0026 
0027 
0028 
0029 template< class Allocator, class RttiPolicy >
0030 class node_state_base : public state_base< Allocator, RttiPolicy >
0031 {
0032   typedef state_base< Allocator, RttiPolicy > base_type;
0033   protected:
0034     //////////////////////////////////////////////////////////////////////////
0035     node_state_base( typename RttiPolicy::id_provider_type idProvider ) :
0036       base_type( idProvider )
0037     {
0038     }
0039 
0040     ~node_state_base() {}
0041 
0042   public:
0043     //////////////////////////////////////////////////////////////////////////
0044     // The following declarations should be private.
0045     // They are only public because many compilers lack template friends.
0046     //////////////////////////////////////////////////////////////////////////
0047     typedef base_type state_base_type;
0048     typedef intrusive_ptr< node_state_base > direct_state_base_ptr_type;
0049     virtual void exit_impl(
0050       direct_state_base_ptr_type & pSelf,
0051       typename base_type::node_state_base_ptr_type & pOutermostUnstableState,
0052       bool performFullExit ) = 0;
0053 };
0054 
0055 //////////////////////////////////////////////////////////////////////////////
0056 template< class OrthogonalRegionCount, class Allocator, class RttiPolicy >
0057 class node_state : public node_state_base< Allocator, RttiPolicy >
0058 {
0059   typedef node_state_base< Allocator, RttiPolicy > base_type;
0060   protected:
0061     //////////////////////////////////////////////////////////////////////////
0062     node_state( typename RttiPolicy::id_provider_type idProvider ) :
0063       base_type( idProvider )
0064     {
0065       for ( orthogonal_position_type pos = 0; 
0066             pos < OrthogonalRegionCount::value; ++pos )
0067       {
0068         pInnerStates[ pos ] = 0;
0069       }
0070     }
0071 
0072     ~node_state() {}
0073 
0074   public:
0075     //////////////////////////////////////////////////////////////////////////
0076     // The following declarations should be private.
0077     // They are only public because many compilers lack template friends.
0078     //////////////////////////////////////////////////////////////////////////
0079     typedef typename base_type::state_base_type state_base_type;
0080 
0081     void add_inner_state( orthogonal_position_type position,
0082                           state_base_type * pInnerState )
0083     {
0084       BOOST_ASSERT( ( position < OrthogonalRegionCount::value ) &&
0085                     ( pInnerStates[ position ] == 0 ) );
0086       pInnerStates[ position ] = pInnerState;
0087     }
0088 
0089     void remove_inner_state( orthogonal_position_type position )
0090     {
0091       BOOST_ASSERT( position < OrthogonalRegionCount::value );
0092       pInnerStates[ position ] = 0;
0093     }
0094 
0095     virtual void remove_from_state_list(
0096       typename state_base_type::state_list_type::iterator & statesEnd,
0097       typename state_base_type::node_state_base_ptr_type &
0098         pOutermostUnstableState,
0099       bool performFullExit )
0100     {
0101       state_base_type ** const pPastEnd =
0102         &pInnerStates[ OrthogonalRegionCount::value ];
0103       // We must not iterate past the last inner state because *this* state
0104       // will no longer exist when the last inner state has been removed
0105       state_base_type ** const pFirstNonNull = std::find_if(
0106         &pInnerStates[ 0 ], pPastEnd, &node_state::is_not_null );
0107 
0108       if ( pFirstNonNull == pPastEnd )
0109       {
0110         // The state does not have inner states but is still alive, this must
0111         // be the outermost unstable state then.
0112         BOOST_ASSERT( get_pointer( pOutermostUnstableState ) == this );
0113         typename state_base_type::node_state_base_ptr_type pSelf =
0114           pOutermostUnstableState;
0115         pSelf->exit_impl( pSelf, pOutermostUnstableState, performFullExit );
0116       }
0117       else
0118       {
0119         // Destroy inner states in the reverse order of construction
0120         for ( state_base_type ** pState = pPastEnd; pState != pFirstNonNull; )
0121         {
0122           --pState;
0123 
0124           // An inner orthogonal state might have been terminated long before,
0125           // that's why we have to check for 0 pointers
0126           if ( *pState != 0 )
0127           {
0128             ( *pState )->remove_from_state_list(
0129               statesEnd, pOutermostUnstableState, performFullExit );
0130           }
0131         }
0132       }
0133     }
0134 
0135     typedef typename base_type::direct_state_base_ptr_type
0136       direct_state_base_ptr_type;
0137 
0138   private:
0139     //////////////////////////////////////////////////////////////////////////
0140     static bool is_not_null( const state_base_type * pInner )
0141     {
0142       return pInner != 0;
0143     }
0144 
0145     state_base_type * pInnerStates[ OrthogonalRegionCount::value ];
0146 };
0147 
0148 
0149 
0150 } // namespace detail
0151 } // namespace statechart
0152 } // namespace boost
0153 
0154 
0155 
0156 #endif