]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/statechart/detail/node_state.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / statechart / detail / node_state.hpp
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