• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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