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
0005
0006
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
0045
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
0077
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
0104
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
0111
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
0120 for ( state_base_type ** pState = pPastEnd; pState != pFirstNonNull; )
0121 {
0122 --pState;
0123
0124
0125
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 }
0151 }
0152 }
0153
0154
0155
0156 #endif