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