1 #ifndef BOOST_STATECHART_DETAIL_NODE_STATE_HPP_INCLUDED 2 #define BOOST_STATECHART_DETAIL_NODE_STATE_HPP_INCLUDED 3 ////////////////////////////////////////////////////////////////////////////// 4 // Copyright 2002-2006 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 9 10 11 #include <boost/statechart/detail/state_base.hpp> 12 13 #include <boost/intrusive_ptr.hpp> 14 #include <boost/assert.hpp> // BOOST_ASSERT 15 16 #include <algorithm> // std::find_if 17 18 19 20 namespace boost 21 { 22 namespace statechart 23 { 24 namespace detail 25 { 26 27 28 29 template< class Allocator, class RttiPolicy > 30 class node_state_base : public state_base< Allocator, RttiPolicy > 31 { 32 typedef state_base< Allocator, RttiPolicy > base_type; 33 protected: 34 ////////////////////////////////////////////////////////////////////////// node_state_base(typename RttiPolicy::id_provider_type idProvider)35 node_state_base( typename RttiPolicy::id_provider_type idProvider ) : 36 base_type( idProvider ) 37 { 38 } 39 ~node_state_base()40 ~node_state_base() {} 41 42 public: 43 ////////////////////////////////////////////////////////////////////////// 44 // The following declarations should be private. 45 // They are only public because many compilers lack template friends. 46 ////////////////////////////////////////////////////////////////////////// 47 typedef base_type state_base_type; 48 typedef intrusive_ptr< node_state_base > direct_state_base_ptr_type; 49 virtual void exit_impl( 50 direct_state_base_ptr_type & pSelf, 51 typename base_type::node_state_base_ptr_type & pOutermostUnstableState, 52 bool performFullExit ) = 0; 53 }; 54 55 ////////////////////////////////////////////////////////////////////////////// 56 template< class OrthogonalRegionCount, class Allocator, class RttiPolicy > 57 class node_state : public node_state_base< Allocator, RttiPolicy > 58 { 59 typedef node_state_base< Allocator, RttiPolicy > base_type; 60 protected: 61 ////////////////////////////////////////////////////////////////////////// node_state(typename RttiPolicy::id_provider_type idProvider)62 node_state( typename RttiPolicy::id_provider_type idProvider ) : 63 base_type( idProvider ) 64 { 65 for ( orthogonal_position_type pos = 0; 66 pos < OrthogonalRegionCount::value; ++pos ) 67 { 68 pInnerStates[ pos ] = 0; 69 } 70 } 71 ~node_state()72 ~node_state() {} 73 74 public: 75 ////////////////////////////////////////////////////////////////////////// 76 // The following declarations should be private. 77 // They are only public because many compilers lack template friends. 78 ////////////////////////////////////////////////////////////////////////// 79 typedef typename base_type::state_base_type state_base_type; 80 add_inner_state(orthogonal_position_type position,state_base_type * pInnerState)81 void add_inner_state( orthogonal_position_type position, 82 state_base_type * pInnerState ) 83 { 84 BOOST_ASSERT( ( position < OrthogonalRegionCount::value ) && 85 ( pInnerStates[ position ] == 0 ) ); 86 pInnerStates[ position ] = pInnerState; 87 } 88 remove_inner_state(orthogonal_position_type position)89 void remove_inner_state( orthogonal_position_type position ) 90 { 91 BOOST_ASSERT( position < OrthogonalRegionCount::value ); 92 pInnerStates[ position ] = 0; 93 } 94 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)95 virtual void remove_from_state_list( 96 typename state_base_type::state_list_type::iterator & statesEnd, 97 typename state_base_type::node_state_base_ptr_type & 98 pOutermostUnstableState, 99 bool performFullExit ) 100 { 101 state_base_type ** const pPastEnd = 102 &pInnerStates[ OrthogonalRegionCount::value ]; 103 // We must not iterate past the last inner state because *this* state 104 // will no longer exist when the last inner state has been removed 105 state_base_type ** const pFirstNonNull = std::find_if( 106 &pInnerStates[ 0 ], pPastEnd, &node_state::is_not_null ); 107 108 if ( pFirstNonNull == pPastEnd ) 109 { 110 // The state does not have inner states but is still alive, this must 111 // be the outermost unstable state then. 112 BOOST_ASSERT( get_pointer( pOutermostUnstableState ) == this ); 113 typename state_base_type::node_state_base_ptr_type pSelf = 114 pOutermostUnstableState; 115 pSelf->exit_impl( pSelf, pOutermostUnstableState, performFullExit ); 116 } 117 else 118 { 119 // Destroy inner states in the reverse order of construction 120 for ( state_base_type ** pState = pPastEnd; pState != pFirstNonNull; ) 121 { 122 --pState; 123 124 // An inner orthogonal state might have been terminated long before, 125 // that's why we have to check for 0 pointers 126 if ( *pState != 0 ) 127 { 128 ( *pState )->remove_from_state_list( 129 statesEnd, pOutermostUnstableState, performFullExit ); 130 } 131 } 132 } 133 } 134 135 typedef typename base_type::direct_state_base_ptr_type 136 direct_state_base_ptr_type; 137 138 private: 139 ////////////////////////////////////////////////////////////////////////// is_not_null(const state_base_type * pInner)140 static bool is_not_null( const state_base_type * pInner ) 141 { 142 return pInner != 0; 143 } 144 145 state_base_type * pInnerStates[ OrthogonalRegionCount::value ]; 146 }; 147 148 149 150 } // namespace detail 151 } // namespace statechart 152 } // namespace boost 153 154 155 156 #endif 157