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 | ////////////////////////////////////////////////////////////////////////// |
---|
35 | node_state_base( typename RttiPolicy::id_provider_type idProvider ) : |
---|
36 | base_type( idProvider ) |
---|
37 | { |
---|
38 | } |
---|
39 | |
---|
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 | ////////////////////////////////////////////////////////////////////////// |
---|
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 | |
---|
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 | |
---|
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 | |
---|
89 | void remove_inner_state( orthogonal_position_type position ) |
---|
90 | { |
---|
91 | BOOST_ASSERT( position < OrthogonalRegionCount::value ); |
---|
92 | pInnerStates[ position ] = 0; |
---|
93 | } |
---|
94 | |
---|
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 | ////////////////////////////////////////////////////////////////////////// |
---|
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 |
---|