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 //////////////////////////////////////////////////////////////////////////////
11 #include <boost/statechart/detail/state_base.hpp>
13 #include <boost/intrusive_ptr.hpp>
14 #include <boost/assert.hpp> // BOOST_ASSERT
16 #include <algorithm> // std::find_if
29 template< class Allocator
, class RttiPolicy
>
30 class node_state_base
: public state_base
< Allocator
, RttiPolicy
>
32 typedef state_base
< Allocator
, RttiPolicy
> base_type
;
34 //////////////////////////////////////////////////////////////////////////
35 node_state_base( typename
RttiPolicy::id_provider_type idProvider
) :
36 base_type( idProvider
)
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;
55 //////////////////////////////////////////////////////////////////////////////
56 template< class OrthogonalRegionCount
, class Allocator
, class RttiPolicy
>
57 class node_state
: public node_state_base
< Allocator
, RttiPolicy
>
59 typedef node_state_base
< Allocator
, RttiPolicy
> base_type
;
61 //////////////////////////////////////////////////////////////////////////
62 node_state( typename
RttiPolicy::id_provider_type idProvider
) :
63 base_type( idProvider
)
65 for ( orthogonal_position_type pos
= 0;
66 pos
< OrthogonalRegionCount::value
; ++pos
)
68 pInnerStates
[ pos
] = 0;
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
;
81 void add_inner_state( orthogonal_position_type position
,
82 state_base_type
* pInnerState
)
84 BOOST_ASSERT( ( position
< OrthogonalRegionCount::value
) &&
85 ( pInnerStates
[ position
] == 0 ) );
86 pInnerStates
[ position
] = pInnerState
;
89 void remove_inner_state( orthogonal_position_type position
)
91 BOOST_ASSERT( position
< OrthogonalRegionCount::value
);
92 pInnerStates
[ position
] = 0;
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
)
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
);
108 if ( pFirstNonNull
== pPastEnd
)
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
);
119 // Destroy inner states in the reverse order of construction
120 for ( state_base_type
** pState
= pPastEnd
; pState
!= pFirstNonNull
; )
124 // An inner orthogonal state might have been terminated long before,
125 // that's why we have to check for 0 pointers
128 ( *pState
)->remove_from_state_list(
129 statesEnd
, pOutermostUnstableState
, performFullExit
);
135 typedef typename
base_type::direct_state_base_ptr_type
136 direct_state_base_ptr_type
;
139 //////////////////////////////////////////////////////////////////////////
140 static bool is_not_null( const state_base_type
* pInner
)
145 state_base_type
* pInnerStates
[ OrthogonalRegionCount::value
];
150 } // namespace detail
151 } // namespace statechart