| 1 | #ifndef BOOST_STATECHART_STATE_MACHINE_HPP_INCLUDED | 
|---|
| 2 | #define BOOST_STATECHART_STATE_MACHINE_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/event.hpp> | 
|---|
| 12 | #include <boost/statechart/null_exception_translator.hpp> | 
|---|
| 13 | #include <boost/statechart/result.hpp> | 
|---|
| 14 |  | 
|---|
| 15 | #include <boost/statechart/detail/rtti_policy.hpp> | 
|---|
| 16 | #include <boost/statechart/detail/state_base.hpp> | 
|---|
| 17 | #include <boost/statechart/detail/leaf_state.hpp> | 
|---|
| 18 | #include <boost/statechart/detail/node_state.hpp> | 
|---|
| 19 | #include <boost/statechart/detail/constructor.hpp> | 
|---|
| 20 | #include <boost/statechart/detail/avoid_unused_warning.hpp> | 
|---|
| 21 |  | 
|---|
| 22 | #include <boost/mpl/list.hpp> | 
|---|
| 23 | #include <boost/mpl/clear.hpp> | 
|---|
| 24 | #include <boost/mpl/if.hpp> | 
|---|
| 25 | #include <boost/mpl/at.hpp> | 
|---|
| 26 | #include <boost/mpl/integral_c.hpp> | 
|---|
| 27 | #include <boost/mpl/minus.hpp> | 
|---|
| 28 | #include <boost/mpl/equal_to.hpp> | 
|---|
| 29 |  | 
|---|
| 30 | #include <boost/intrusive_ptr.hpp> | 
|---|
| 31 | #include <boost/type_traits/is_pointer.hpp> | 
|---|
| 32 | #include <boost/type_traits/remove_reference.hpp> | 
|---|
| 33 | #include <boost/noncopyable.hpp> | 
|---|
| 34 | #include <boost/assert.hpp> | 
|---|
| 35 | #include <boost/static_assert.hpp> | 
|---|
| 36 | #include <boost/cast.hpp> // boost::polymorphic_downcast | 
|---|
| 37 | // BOOST_NO_EXCEPTIONS, BOOST_MSVC, BOOST_MSVC_STD_ITERATOR | 
|---|
| 38 | #include <boost/config.hpp> | 
|---|
| 39 |  | 
|---|
| 40 | #include <boost/detail/allocator_utilities.hpp> | 
|---|
| 41 |  | 
|---|
| 42 | #ifdef BOOST_MSVC | 
|---|
| 43 | #  pragma warning( push ) | 
|---|
| 44 | #  pragma warning( disable: 4702 ) // unreachable code (in release mode only) | 
|---|
| 45 | #endif | 
|---|
| 46 |  | 
|---|
| 47 | #include <map> | 
|---|
| 48 |  | 
|---|
| 49 | #ifdef BOOST_MSVC | 
|---|
| 50 | #  pragma warning( pop ) | 
|---|
| 51 | #endif | 
|---|
| 52 |  | 
|---|
| 53 | #include <memory>   // std::allocator | 
|---|
| 54 | #include <typeinfo> // std::bad_cast | 
|---|
| 55 | #include <functional> // std::less | 
|---|
| 56 | #include <iterator> | 
|---|
| 57 |  | 
|---|
| 58 |  | 
|---|
| 59 |  | 
|---|
| 60 | #ifdef BOOST_MSVC | 
|---|
| 61 | // We permanently turn off the following level 4 warnings because users will | 
|---|
| 62 | // have to do so themselves anyway if we turn them back on | 
|---|
| 63 | #  pragma warning( disable: 4511 ) // copy constructor could not be generated | 
|---|
| 64 | #  pragma warning( disable: 4512 ) // assignment op could not be generated | 
|---|
| 65 | #endif | 
|---|
| 66 |  | 
|---|
| 67 |  | 
|---|
| 68 |  | 
|---|
| 69 | namespace boost | 
|---|
| 70 | { | 
|---|
| 71 | namespace statechart | 
|---|
| 72 | { | 
|---|
| 73 | namespace detail | 
|---|
| 74 | { | 
|---|
| 75 |  | 
|---|
| 76 |  | 
|---|
| 77 |  | 
|---|
| 78 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
| 79 | template< class StateBaseType, class EventBaseType, class IdType > | 
|---|
| 80 | class send_function | 
|---|
| 81 | { | 
|---|
| 82 |   public: | 
|---|
| 83 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 84 |     send_function( | 
|---|
| 85 |       StateBaseType & toState, | 
|---|
| 86 |       const EventBaseType & evt, | 
|---|
| 87 |       IdType eventType | 
|---|
| 88 |     ) : | 
|---|
| 89 |       toState_( toState ), evt_( evt ), eventType_( eventType ) | 
|---|
| 90 |     { | 
|---|
| 91 |     } | 
|---|
| 92 |  | 
|---|
| 93 |     result operator()() | 
|---|
| 94 |     { | 
|---|
| 95 |       return detail::result_utility::make_result( | 
|---|
| 96 |         toState_.react_impl( evt_, eventType_ ) ); | 
|---|
| 97 |     } | 
|---|
| 98 |  | 
|---|
| 99 |   private: | 
|---|
| 100 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 101 |     StateBaseType & toState_; | 
|---|
| 102 |     const EventBaseType & evt_; | 
|---|
| 103 |     IdType eventType_; | 
|---|
| 104 | }; | 
|---|
| 105 |  | 
|---|
| 106 |  | 
|---|
| 107 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
| 108 | struct state_cast_impl_pointer_target | 
|---|
| 109 | { | 
|---|
| 110 |   public: | 
|---|
| 111 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 112 |     template< class StateBaseType > | 
|---|
| 113 |     static const StateBaseType * deref_if_necessary( | 
|---|
| 114 |       const StateBaseType * pState ) | 
|---|
| 115 |     { | 
|---|
| 116 |       return pState; | 
|---|
| 117 |     } | 
|---|
| 118 |  | 
|---|
| 119 |     template< class Target, class IdType > | 
|---|
| 120 |     static IdType type_id() | 
|---|
| 121 |     { | 
|---|
| 122 |       Target p = 0; | 
|---|
| 123 |       return type_id_impl< IdType >( p ); | 
|---|
| 124 |     } | 
|---|
| 125 |  | 
|---|
| 126 |     static bool found( const void * pFound ) | 
|---|
| 127 |     { | 
|---|
| 128 |       return pFound != 0; | 
|---|
| 129 |     } | 
|---|
| 130 |  | 
|---|
| 131 |     template< class Target > | 
|---|
| 132 |     static Target not_found() | 
|---|
| 133 |     { | 
|---|
| 134 |       return 0; | 
|---|
| 135 |     } | 
|---|
| 136 |  | 
|---|
| 137 |   private: | 
|---|
| 138 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 139 |     template< class IdType, class Type > | 
|---|
| 140 |     static IdType type_id_impl( const Type * ) | 
|---|
| 141 |     { | 
|---|
| 142 |       return Type::static_type(); | 
|---|
| 143 |     } | 
|---|
| 144 | }; | 
|---|
| 145 |  | 
|---|
| 146 | struct state_cast_impl_reference_target | 
|---|
| 147 | { | 
|---|
| 148 |   template< class StateBaseType > | 
|---|
| 149 |   static const StateBaseType & deref_if_necessary( | 
|---|
| 150 |     const StateBaseType * pState ) | 
|---|
| 151 |   { | 
|---|
| 152 |     return *pState; | 
|---|
| 153 |   } | 
|---|
| 154 |  | 
|---|
| 155 |   template< class Target, class IdType > | 
|---|
| 156 |   static IdType type_id() | 
|---|
| 157 |   { | 
|---|
| 158 |     return remove_reference< Target >::type::static_type(); | 
|---|
| 159 |   } | 
|---|
| 160 |  | 
|---|
| 161 |   template< class Dummy > | 
|---|
| 162 |   static bool found( const Dummy & ) | 
|---|
| 163 |   { | 
|---|
| 164 |     return true; | 
|---|
| 165 |   } | 
|---|
| 166 |  | 
|---|
| 167 |   template< class Target > | 
|---|
| 168 |   static Target not_found() | 
|---|
| 169 |   { | 
|---|
| 170 |     throw std::bad_cast(); | 
|---|
| 171 |   } | 
|---|
| 172 | }; | 
|---|
| 173 |  | 
|---|
| 174 | template< class Target > | 
|---|
| 175 | struct state_cast_impl : public mpl::if_< | 
|---|
| 176 |   is_pointer< Target >, | 
|---|
| 177 |   state_cast_impl_pointer_target, | 
|---|
| 178 |   state_cast_impl_reference_target | 
|---|
| 179 | >::type {}; | 
|---|
| 180 |  | 
|---|
| 181 |  | 
|---|
| 182 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
| 183 | template< class RttiPolicy > | 
|---|
| 184 | class history_key | 
|---|
| 185 | { | 
|---|
| 186 |   public: | 
|---|
| 187 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 188 |     template< class HistorizedState > | 
|---|
| 189 |     static history_key make_history_key() | 
|---|
| 190 |     { | 
|---|
| 191 |       return history_key( | 
|---|
| 192 |         HistorizedState::context_type::static_type(), | 
|---|
| 193 |         HistorizedState::orthogonal_position::value ); | 
|---|
| 194 |     } | 
|---|
| 195 |  | 
|---|
| 196 |     typename RttiPolicy::id_type history_context_type() const | 
|---|
| 197 |     { | 
|---|
| 198 |       return historyContextType_; | 
|---|
| 199 |     } | 
|---|
| 200 |  | 
|---|
| 201 |     friend bool operator<( | 
|---|
| 202 |       const history_key & left, const history_key & right ) | 
|---|
| 203 |     { | 
|---|
| 204 |       return | 
|---|
| 205 |         std::less< typename RttiPolicy::id_type >()(  | 
|---|
| 206 |           left.historyContextType_, right.historyContextType_ ) || | 
|---|
| 207 |         ( ( left.historyContextType_ == right.historyContextType_ ) && | 
|---|
| 208 |           ( left.historizedOrthogonalRegion_ < | 
|---|
| 209 |             right.historizedOrthogonalRegion_ ) ); | 
|---|
| 210 |     } | 
|---|
| 211 |  | 
|---|
| 212 |   private: | 
|---|
| 213 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 214 |     history_key( | 
|---|
| 215 |       typename RttiPolicy::id_type historyContextType,  | 
|---|
| 216 |       orthogonal_position_type historizedOrthogonalRegion | 
|---|
| 217 |     ) : | 
|---|
| 218 |       historyContextType_( historyContextType ), | 
|---|
| 219 |       historizedOrthogonalRegion_( historizedOrthogonalRegion ) | 
|---|
| 220 |     { | 
|---|
| 221 |     } | 
|---|
| 222 |  | 
|---|
| 223 |     const typename RttiPolicy::id_type historyContextType_; | 
|---|
| 224 |     const orthogonal_position_type historizedOrthogonalRegion_; | 
|---|
| 225 | }; | 
|---|
| 226 |  | 
|---|
| 227 |  | 
|---|
| 228 |  | 
|---|
| 229 | } // namespace detail | 
|---|
| 230 |  | 
|---|
| 231 |  | 
|---|
| 232 |  | 
|---|
| 233 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
| 234 | template< class MostDerived, | 
|---|
| 235 |           class InitialState,  | 
|---|
| 236 |           class Allocator = std::allocator< void >, | 
|---|
| 237 |           class ExceptionTranslator = null_exception_translator > | 
|---|
| 238 | class state_machine : noncopyable | 
|---|
| 239 | { | 
|---|
| 240 |   public: | 
|---|
| 241 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 242 |     typedef Allocator allocator_type; | 
|---|
| 243 |     typedef detail::rtti_policy rtti_policy_type; | 
|---|
| 244 |     typedef event_base event_base_type; | 
|---|
| 245 |     typedef intrusive_ptr< const event_base_type > event_base_ptr_type; | 
|---|
| 246 |  | 
|---|
| 247 |     void initiate() | 
|---|
| 248 |     { | 
|---|
| 249 |       terminate(); | 
|---|
| 250 |  | 
|---|
| 251 |       { | 
|---|
| 252 |         terminator guard( *this ); | 
|---|
| 253 |         detail::result_utility::get_result( translator_( | 
|---|
| 254 |           initial_construct_function( *this ), | 
|---|
| 255 |           exception_event_handler( *this ) ) ); | 
|---|
| 256 |         guard.dismiss(); | 
|---|
| 257 |       } | 
|---|
| 258 |  | 
|---|
| 259 |       process_queued_events(); | 
|---|
| 260 |     } | 
|---|
| 261 |  | 
|---|
| 262 |     void terminate() | 
|---|
| 263 |     { | 
|---|
| 264 |       terminator guard( *this ); | 
|---|
| 265 |       detail::result_utility::get_result( translator_( | 
|---|
| 266 |         terminate_function( *this ), | 
|---|
| 267 |         exception_event_handler( *this ) ) ); | 
|---|
| 268 |       guard.dismiss(); | 
|---|
| 269 |     } | 
|---|
| 270 |  | 
|---|
| 271 |     bool terminated() const | 
|---|
| 272 |     { | 
|---|
| 273 |       return pOutermostState_ == 0; | 
|---|
| 274 |     } | 
|---|
| 275 |  | 
|---|
| 276 |     void process_event( const event_base_type & evt ) | 
|---|
| 277 |     { | 
|---|
| 278 |       send_event( evt ); | 
|---|
| 279 |       process_queued_events(); | 
|---|
| 280 |     } | 
|---|
| 281 |  | 
|---|
| 282 |     template< class Target > | 
|---|
| 283 |     Target state_cast() const | 
|---|
| 284 |     { | 
|---|
| 285 |       typedef detail::state_cast_impl< Target > impl; | 
|---|
| 286 |  | 
|---|
| 287 |       for ( typename state_list_type::const_iterator pCurrentLeafState = | 
|---|
| 288 |               currentStates_.begin(); | 
|---|
| 289 |             pCurrentLeafState != currentStatesEnd_; | 
|---|
| 290 |             ++pCurrentLeafState ) | 
|---|
| 291 |       { | 
|---|
| 292 |         const state_base_type * pCurrentState( | 
|---|
| 293 |           get_pointer( *pCurrentLeafState ) ); | 
|---|
| 294 |  | 
|---|
| 295 |         while ( pCurrentState != 0 ) | 
|---|
| 296 |         { | 
|---|
| 297 |           // The unnecessary try/catch overhead for pointer targets is | 
|---|
| 298 |           // typically small compared to the cycles dynamic_cast needs | 
|---|
| 299 |           #ifndef BOOST_NO_EXCEPTIONS | 
|---|
| 300 |           try | 
|---|
| 301 |           #endif | 
|---|
| 302 |           { | 
|---|
| 303 |             Target result = dynamic_cast< Target >( | 
|---|
| 304 |               impl::deref_if_necessary( pCurrentState ) ); | 
|---|
| 305 |  | 
|---|
| 306 |             if ( impl::found( result ) ) | 
|---|
| 307 |             { | 
|---|
| 308 |               return result; | 
|---|
| 309 |             } | 
|---|
| 310 |           } | 
|---|
| 311 |           #ifndef BOOST_NO_EXCEPTIONS | 
|---|
| 312 |           // Intentionally swallow std::bad_cast exceptions. We'll throw one | 
|---|
| 313 |           // ourselves when we fail to find a state that can be cast to Target | 
|---|
| 314 |           catch ( const std::bad_cast & ) {} | 
|---|
| 315 |           #endif | 
|---|
| 316 |  | 
|---|
| 317 |           pCurrentState = pCurrentState->outer_state_ptr(); | 
|---|
| 318 |         } | 
|---|
| 319 |       } | 
|---|
| 320 |  | 
|---|
| 321 |       return impl::template not_found< Target >(); | 
|---|
| 322 |     } | 
|---|
| 323 |  | 
|---|
| 324 |     template< class Target > | 
|---|
| 325 |     Target state_downcast() const | 
|---|
| 326 |     { | 
|---|
| 327 |       typedef detail::state_cast_impl< Target > impl; | 
|---|
| 328 |  | 
|---|
| 329 |       typename rtti_policy_type::id_type targetType = | 
|---|
| 330 |         impl::template type_id< Target, rtti_policy_type::id_type >(); | 
|---|
| 331 |  | 
|---|
| 332 |       for ( typename state_list_type::const_iterator pCurrentLeafState = | 
|---|
| 333 |               currentStates_.begin(); | 
|---|
| 334 |             pCurrentLeafState != currentStatesEnd_; | 
|---|
| 335 |             ++pCurrentLeafState ) | 
|---|
| 336 |       { | 
|---|
| 337 |         const state_base_type * pCurrentState( | 
|---|
| 338 |           get_pointer( *pCurrentLeafState ) ); | 
|---|
| 339 |  | 
|---|
| 340 |         while ( pCurrentState != 0 ) | 
|---|
| 341 |         { | 
|---|
| 342 |           if ( pCurrentState->dynamic_type() == targetType ) | 
|---|
| 343 |           { | 
|---|
| 344 |             return static_cast< Target >( | 
|---|
| 345 |               impl::deref_if_necessary( pCurrentState ) ); | 
|---|
| 346 |           } | 
|---|
| 347 |  | 
|---|
| 348 |           pCurrentState = pCurrentState->outer_state_ptr(); | 
|---|
| 349 |         } | 
|---|
| 350 |       } | 
|---|
| 351 |  | 
|---|
| 352 |       return impl::template not_found< Target >(); | 
|---|
| 353 |     } | 
|---|
| 354 |  | 
|---|
| 355 |     typedef detail::state_base< allocator_type, rtti_policy_type > | 
|---|
| 356 |       state_base_type; | 
|---|
| 357 |  | 
|---|
| 358 |     class state_iterator : public std::iterator< | 
|---|
| 359 |       std::forward_iterator_tag, | 
|---|
| 360 |       state_base_type, std::ptrdiff_t | 
|---|
| 361 |       #ifndef BOOST_MSVC_STD_ITERATOR | 
|---|
| 362 |       , const state_base_type *, const state_base_type & | 
|---|
| 363 |       #endif | 
|---|
| 364 |     > | 
|---|
| 365 |     { | 
|---|
| 366 |       public: | 
|---|
| 367 |         ////////////////////////////////////////////////////////////////////// | 
|---|
| 368 |         explicit state_iterator( | 
|---|
| 369 |           typename state_base_type::state_list_type::const_iterator  | 
|---|
| 370 |             baseIterator | 
|---|
| 371 |         ) : baseIterator_( baseIterator ) {} | 
|---|
| 372 |  | 
|---|
| 373 |         const state_base_type & operator*() const { return **baseIterator_; } | 
|---|
| 374 |         const state_base_type * operator->() const | 
|---|
| 375 |         { | 
|---|
| 376 |           return &**baseIterator_; | 
|---|
| 377 |         } | 
|---|
| 378 |  | 
|---|
| 379 |         state_iterator & operator++() { ++baseIterator_; return *this; } | 
|---|
| 380 |         state_iterator operator++( int ) | 
|---|
| 381 |         { | 
|---|
| 382 |           return state_iterator( baseIterator_++ ); | 
|---|
| 383 |         } | 
|---|
| 384 |  | 
|---|
| 385 |         bool operator==( const state_iterator & right ) const | 
|---|
| 386 |         { | 
|---|
| 387 |           return baseIterator_ == right.baseIterator_; | 
|---|
| 388 |         } | 
|---|
| 389 |         bool operator!=( const state_iterator & right ) const | 
|---|
| 390 |         { | 
|---|
| 391 |           return !( *this == right ); | 
|---|
| 392 |         } | 
|---|
| 393 |  | 
|---|
| 394 |       private: | 
|---|
| 395 |         typename state_base_type::state_list_type::const_iterator | 
|---|
| 396 |           baseIterator_; | 
|---|
| 397 |     }; | 
|---|
| 398 |  | 
|---|
| 399 |     state_iterator state_begin() const | 
|---|
| 400 |     { | 
|---|
| 401 |       return state_iterator( currentStates_.begin() ); | 
|---|
| 402 |     } | 
|---|
| 403 |  | 
|---|
| 404 |     state_iterator state_end() const | 
|---|
| 405 |     { | 
|---|
| 406 |       return state_iterator( currentStatesEnd_ ); | 
|---|
| 407 |     } | 
|---|
| 408 |  | 
|---|
| 409 |     void unconsumed_event( const event_base & ) {} | 
|---|
| 410 |  | 
|---|
| 411 |   protected: | 
|---|
| 412 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 413 |     state_machine() : | 
|---|
| 414 |       currentStatesEnd_( currentStates_.end() ), | 
|---|
| 415 |       pOutermostState_( 0 ), | 
|---|
| 416 |       isInnermostCommonOuter_( false ), | 
|---|
| 417 |       performFullExit_( true ) | 
|---|
| 418 |     { | 
|---|
| 419 |     } | 
|---|
| 420 |  | 
|---|
| 421 |     // This destructor was only made virtual so that that | 
|---|
| 422 |     // polymorphic_downcast can be used to cast to MostDerived. | 
|---|
| 423 |     virtual ~state_machine() | 
|---|
| 424 |     { | 
|---|
| 425 |       terminate_impl( false ); | 
|---|
| 426 |     } | 
|---|
| 427 |  | 
|---|
| 428 |   public: | 
|---|
| 429 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 430 |     // The following declarations should be protected. | 
|---|
| 431 |     // They are only public because many compilers lack template friends. | 
|---|
| 432 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 433 |     void post_event( const event_base_ptr_type & pEvent ) | 
|---|
| 434 |     { | 
|---|
| 435 |       BOOST_ASSERT( get_pointer( pEvent ) != 0 ); | 
|---|
| 436 |       eventQueue_.push_back( pEvent ); | 
|---|
| 437 |     } | 
|---|
| 438 |  | 
|---|
| 439 |     void post_event( const event_base & evt ) | 
|---|
| 440 |     { | 
|---|
| 441 |       post_event( evt.intrusive_from_this() ); | 
|---|
| 442 |     } | 
|---|
| 443 |  | 
|---|
| 444 |   public: | 
|---|
| 445 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 446 |     // The following declarations should be private. | 
|---|
| 447 |     // They are only public because many compilers lack template friends. | 
|---|
| 448 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 449 |     typedef MostDerived inner_context_type; | 
|---|
| 450 |     typedef mpl::integral_c< detail::orthogonal_position_type, 0 > | 
|---|
| 451 |       inner_orthogonal_position; | 
|---|
| 452 |     typedef mpl::integral_c< detail::orthogonal_position_type, 1 > | 
|---|
| 453 |       no_of_orthogonal_regions; | 
|---|
| 454 |  | 
|---|
| 455 |     typedef MostDerived outermost_context_type; | 
|---|
| 456 |     typedef state_machine outermost_context_base_type; | 
|---|
| 457 |     typedef state_machine * inner_context_ptr_type; | 
|---|
| 458 |     typedef typename state_base_type::node_state_base_ptr_type | 
|---|
| 459 |       node_state_base_ptr_type; | 
|---|
| 460 |     typedef typename state_base_type::leaf_state_ptr_type leaf_state_ptr_type; | 
|---|
| 461 |     typedef typename state_base_type::state_list_type state_list_type; | 
|---|
| 462 |  | 
|---|
| 463 |     typedef mpl::clear< mpl::list<> >::type context_type_list; | 
|---|
| 464 |  | 
|---|
| 465 |     typedef mpl::bool_< false > shallow_history; | 
|---|
| 466 |     typedef mpl::bool_< false > deep_history; | 
|---|
| 467 |     typedef mpl::bool_< false > inherited_deep_history; | 
|---|
| 468 |  | 
|---|
| 469 |     detail::reaction_result react_impl( | 
|---|
| 470 |       const event_base_type &, | 
|---|
| 471 |       typename rtti_policy_type::id_type ) | 
|---|
| 472 |     { | 
|---|
| 473 |       return detail::do_forward_event; | 
|---|
| 474 |     } | 
|---|
| 475 |  | 
|---|
| 476 |     void exit_impl( | 
|---|
| 477 |       inner_context_ptr_type &, | 
|---|
| 478 |       typename state_base_type::node_state_base_ptr_type &, | 
|---|
| 479 |       bool ) {} | 
|---|
| 480 |  | 
|---|
| 481 |     void set_outermost_unstable_state( | 
|---|
| 482 |       typename state_base_type::node_state_base_ptr_type & | 
|---|
| 483 |         pOutermostUnstableState ) | 
|---|
| 484 |     { | 
|---|
| 485 |       pOutermostUnstableState = 0; | 
|---|
| 486 |     } | 
|---|
| 487 |  | 
|---|
| 488 |     // Returns a reference to the context identified by the template | 
|---|
| 489 |     // parameter. This can either be _this_ object or one of its direct or | 
|---|
| 490 |     // indirect contexts. | 
|---|
| 491 |     template< class Context > | 
|---|
| 492 |     Context & context() | 
|---|
| 493 |     { | 
|---|
| 494 |       // As we are in the outermost context here, only this object can be | 
|---|
| 495 |       // returned. | 
|---|
| 496 |       return *polymorphic_downcast< MostDerived * >( this ); | 
|---|
| 497 |     } | 
|---|
| 498 |  | 
|---|
| 499 |     template< class Context > | 
|---|
| 500 |     const Context & context() const | 
|---|
| 501 |     { | 
|---|
| 502 |       // As we are in the outermost context here, only this object can be | 
|---|
| 503 |       // returned. | 
|---|
| 504 |       return *polymorphic_downcast< const MostDerived * >( this ); | 
|---|
| 505 |     } | 
|---|
| 506 |  | 
|---|
| 507 |     outermost_context_type & outermost_context() | 
|---|
| 508 |     { | 
|---|
| 509 |       return *polymorphic_downcast< MostDerived * >( this ); | 
|---|
| 510 |     } | 
|---|
| 511 |  | 
|---|
| 512 |     const outermost_context_type & outermost_context() const | 
|---|
| 513 |     { | 
|---|
| 514 |       return *polymorphic_downcast< const MostDerived * >( this ); | 
|---|
| 515 |     } | 
|---|
| 516 |  | 
|---|
| 517 |     outermost_context_base_type & outermost_context_base() | 
|---|
| 518 |     { | 
|---|
| 519 |       return *this; | 
|---|
| 520 |     } | 
|---|
| 521 |  | 
|---|
| 522 |     const outermost_context_base_type & outermost_context_base() const | 
|---|
| 523 |     { | 
|---|
| 524 |       return *this; | 
|---|
| 525 |     } | 
|---|
| 526 |  | 
|---|
| 527 |     void terminate_as_reaction( state_base_type & theState ) | 
|---|
| 528 |     { | 
|---|
| 529 |       terminate_impl( theState, performFullExit_ ); | 
|---|
| 530 |       pOutermostUnstableState_ = 0; | 
|---|
| 531 |     } | 
|---|
| 532 |  | 
|---|
| 533 |     void terminate_as_part_of_transit( state_base_type & theState ) | 
|---|
| 534 |     { | 
|---|
| 535 |       terminate_impl( theState, performFullExit_ ); | 
|---|
| 536 |       isInnermostCommonOuter_ = true; | 
|---|
| 537 |     } | 
|---|
| 538 |  | 
|---|
| 539 |     void terminate_as_part_of_transit( state_machine & ) | 
|---|
| 540 |     { | 
|---|
| 541 |       terminate_impl( *pOutermostState_, performFullExit_ ); | 
|---|
| 542 |       isInnermostCommonOuter_ = true; | 
|---|
| 543 |     } | 
|---|
| 544 |  | 
|---|
| 545 |  | 
|---|
| 546 |     template< class State > | 
|---|
| 547 |     void add( const intrusive_ptr< State > & pState ) | 
|---|
| 548 |     { | 
|---|
| 549 |       // The second dummy argument is necessary because the call to the | 
|---|
| 550 |       // overloaded function add_impl would otherwise be ambiguous. | 
|---|
| 551 |       node_state_base_ptr_type pNewOutermostUnstableStateCandidate = | 
|---|
| 552 |         add_impl( pState, *pState ); | 
|---|
| 553 |  | 
|---|
| 554 |       if ( isInnermostCommonOuter_ || | 
|---|
| 555 |         is_in_highest_orthogonal_region< State >() && | 
|---|
| 556 |         ( get_pointer( pOutermostUnstableState_ ) == | 
|---|
| 557 |           pState->State::outer_state_ptr() ) ) | 
|---|
| 558 |       { | 
|---|
| 559 |         isInnermostCommonOuter_ = false; | 
|---|
| 560 |         pOutermostUnstableState_ = pNewOutermostUnstableStateCandidate; | 
|---|
| 561 |       } | 
|---|
| 562 |     } | 
|---|
| 563 |  | 
|---|
| 564 |  | 
|---|
| 565 |     void add_inner_state( | 
|---|
| 566 |       detail::orthogonal_position_type position, | 
|---|
| 567 |       state_base_type * pOutermostState ) | 
|---|
| 568 |     { | 
|---|
| 569 |       BOOST_ASSERT( position == 0 ); | 
|---|
| 570 |       detail::avoid_unused_warning( position ); | 
|---|
| 571 |       pOutermostState_ = pOutermostState; | 
|---|
| 572 |     } | 
|---|
| 573 |  | 
|---|
| 574 |     void remove_inner_state( detail::orthogonal_position_type position ) | 
|---|
| 575 |     { | 
|---|
| 576 |       BOOST_ASSERT( position == 0 ); | 
|---|
| 577 |       detail::avoid_unused_warning( position ); | 
|---|
| 578 |       pOutermostState_ = 0; | 
|---|
| 579 |     } | 
|---|
| 580 |  | 
|---|
| 581 |  | 
|---|
| 582 |     void defer_event( | 
|---|
| 583 |       const event_base_type & evt, | 
|---|
| 584 |       const state_base_type * pForState ) | 
|---|
| 585 |     { | 
|---|
| 586 |       deferredMap_[ pForState ].push_back( evt.intrusive_from_this() ); | 
|---|
| 587 |     } | 
|---|
| 588 |  | 
|---|
| 589 |     void release_events( const state_base_type * pForState ) | 
|---|
| 590 |     { | 
|---|
| 591 |       const typename deferred_map_type::iterator pFound = | 
|---|
| 592 |         deferredMap_.find( pForState ); | 
|---|
| 593 |  | 
|---|
| 594 |       // We are not guaranteed to find an entry because a state is marked for | 
|---|
| 595 |       // having deferred events _before_ the event is actually deferred. An | 
|---|
| 596 |       // exception might be thrown during deferral. | 
|---|
| 597 |       if ( pFound != deferredMap_.end() ) | 
|---|
| 598 |       { | 
|---|
| 599 |         eventQueue_.splice( eventQueue_.end(), pFound->second ); | 
|---|
| 600 |         deferredMap_.erase( pFound ); | 
|---|
| 601 |       } | 
|---|
| 602 |     } | 
|---|
| 603 |  | 
|---|
| 604 |  | 
|---|
| 605 |     template< class HistorizedState > | 
|---|
| 606 |     void store_shallow_history() | 
|---|
| 607 |     { | 
|---|
| 608 |       // 5.2.10.6 declares that reinterpret_casting a function pointer to a | 
|---|
| 609 |       // different function pointer and back must yield the same value. The | 
|---|
| 610 |       // following reinterpret_cast is the first half of such a sequence. | 
|---|
| 611 |       store_history_impl( | 
|---|
| 612 |         shallowHistoryMap_, | 
|---|
| 613 |         history_key_type::make_history_key< HistorizedState >(), | 
|---|
| 614 |         reinterpret_cast< void (*)() >( &HistorizedState::deep_construct ) ); | 
|---|
| 615 |     } | 
|---|
| 616 |  | 
|---|
| 617 |     template< | 
|---|
| 618 |       class HistoryContext, | 
|---|
| 619 |       detail::orthogonal_position_type orthogonalPosition > | 
|---|
| 620 |     void clear_shallow_history() | 
|---|
| 621 |     { | 
|---|
| 622 |       // If you receive a | 
|---|
| 623 |       // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or | 
|---|
| 624 |       // similar compiler error here then you tried to clear shallow history | 
|---|
| 625 |       // for a state that does not have shallow history. That is, the state | 
|---|
| 626 |       // does not pass either statechart::has_shallow_history or | 
|---|
| 627 |       // statechart::has_full_history to its base class template. | 
|---|
| 628 |       BOOST_STATIC_ASSERT( HistoryContext::shallow_history::value ); | 
|---|
| 629 |  | 
|---|
| 630 |       typedef typename mpl::at_c< | 
|---|
| 631 |         typename HistoryContext::inner_initial_list, | 
|---|
| 632 |         orthogonalPosition >::type historized_state; | 
|---|
| 633 |  | 
|---|
| 634 |       store_history_impl( | 
|---|
| 635 |         shallowHistoryMap_, | 
|---|
| 636 |         history_key_type::make_history_key< historized_state >(), | 
|---|
| 637 |         0 ); | 
|---|
| 638 |     } | 
|---|
| 639 |  | 
|---|
| 640 |     template< class DefaultState > | 
|---|
| 641 |     void construct_with_shallow_history( | 
|---|
| 642 |       const typename DefaultState::context_ptr_type & pContext ) | 
|---|
| 643 |     { | 
|---|
| 644 |       construct_with_history_impl< DefaultState >( | 
|---|
| 645 |         shallowHistoryMap_, pContext ); | 
|---|
| 646 |     } | 
|---|
| 647 |  | 
|---|
| 648 |  | 
|---|
| 649 |     template< class HistorizedState, class LeafState > | 
|---|
| 650 |     void store_deep_history() | 
|---|
| 651 |     { | 
|---|
| 652 |       typedef typename detail::make_context_list< | 
|---|
| 653 |         typename HistorizedState::context_type, | 
|---|
| 654 |         LeafState >::type history_context_list; | 
|---|
| 655 |       typedef detail::constructor<  | 
|---|
| 656 |         history_context_list, outermost_context_base_type > constructor_type; | 
|---|
| 657 |       // 5.2.10.6 declares that reinterpret_casting a function pointer to a | 
|---|
| 658 |       // different function pointer and back must yield the same value. The | 
|---|
| 659 |       // following reinterpret_cast is the first half of such a sequence. | 
|---|
| 660 |       store_history_impl( | 
|---|
| 661 |         deepHistoryMap_,  | 
|---|
| 662 |         history_key_type::make_history_key< HistorizedState >(), | 
|---|
| 663 |         reinterpret_cast< void (*)() >( &constructor_type::construct ) ); | 
|---|
| 664 |     } | 
|---|
| 665 |  | 
|---|
| 666 |     template< | 
|---|
| 667 |       class HistoryContext, | 
|---|
| 668 |       detail::orthogonal_position_type orthogonalPosition > | 
|---|
| 669 |     void clear_deep_history() | 
|---|
| 670 |     { | 
|---|
| 671 |       // If you receive a | 
|---|
| 672 |       // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or | 
|---|
| 673 |       // similar compiler error here then you tried to clear deep history for | 
|---|
| 674 |       // a state that does not have deep history. That is, the state does not | 
|---|
| 675 |       // pass either statechart::has_deep_history or | 
|---|
| 676 |       // statechart::has_full_history to its base class template | 
|---|
| 677 |       BOOST_STATIC_ASSERT( HistoryContext::deep_history::value ); | 
|---|
| 678 |  | 
|---|
| 679 |       typedef typename mpl::at_c< | 
|---|
| 680 |         typename HistoryContext::inner_initial_list, | 
|---|
| 681 |         orthogonalPosition >::type historized_state; | 
|---|
| 682 |  | 
|---|
| 683 |       store_history_impl( | 
|---|
| 684 |         deepHistoryMap_, | 
|---|
| 685 |         history_key_type::make_history_key< historized_state >(), | 
|---|
| 686 |         0 ); | 
|---|
| 687 |     } | 
|---|
| 688 |  | 
|---|
| 689 |     template< class DefaultState > | 
|---|
| 690 |     void construct_with_deep_history( | 
|---|
| 691 |       const typename DefaultState::context_ptr_type & pContext ) | 
|---|
| 692 |     { | 
|---|
| 693 |       construct_with_history_impl< DefaultState >( | 
|---|
| 694 |         deepHistoryMap_, pContext ); | 
|---|
| 695 |     } | 
|---|
| 696 |  | 
|---|
| 697 |   private: // implementation | 
|---|
| 698 |     ////////////////////////////////////////////////////////////////////////// | 
|---|
| 699 |     void initial_construct() | 
|---|
| 700 |     { | 
|---|
| 701 |       InitialState::initial_deep_construct( | 
|---|
| 702 |         *polymorphic_downcast< MostDerived * >( this ) ); | 
|---|
| 703 |     } | 
|---|
| 704 |  | 
|---|
| 705 |     class initial_construct_function | 
|---|
| 706 |     { | 
|---|
| 707 |       public: | 
|---|
| 708 |         ////////////////////////////////////////////////////////////////////// | 
|---|
| 709 |         initial_construct_function( state_machine & machine ) : | 
|---|
| 710 |           machine_( machine ) | 
|---|
| 711 |         { | 
|---|
| 712 |         } | 
|---|
| 713 |  | 
|---|
| 714 |         result operator()() | 
|---|
| 715 |         { | 
|---|
| 716 |           machine_.initial_construct(); | 
|---|
| 717 |           return detail::result_utility::make_result( | 
|---|
| 718 |             detail::do_discard_event ); // there is nothing to be consumed | 
|---|
| 719 |         } | 
|---|
| 720 |  | 
|---|
| 721 |       private: | 
|---|
| 722 |         ////////////////////////////////////////////////////////////////////// | 
|---|
| 723 |         state_machine & machine_; | 
|---|
| 724 |     }; | 
|---|
| 725 |     friend class initial_construct_function; | 
|---|
| 726 |  | 
|---|
| 727 |     class terminate_function | 
|---|
| 728 |     { | 
|---|
| 729 |       public: | 
|---|
| 730 |         ////////////////////////////////////////////////////////////////////// | 
|---|
| 731 |         terminate_function( state_machine & machine ) : machine_( machine ) {} | 
|---|
| 732 |  | 
|---|
| 733 |         result operator()() | 
|---|
| 734 |         { | 
|---|
| 735 |           machine_.terminate_impl( true ); | 
|---|
| 736 |           return detail::result_utility::make_result( | 
|---|
| 737 |             detail::do_discard_event ); // there is nothing to be consumed | 
|---|
| 738 |         } | 
|---|
| 739 |  | 
|---|
| 740 |       private: | 
|---|
| 741 |         ////////////////////////////////////////////////////////////////////// | 
|---|
| 742 |         state_machine & machine_; | 
|---|
| 743 |     }; | 
|---|
| 744 |     friend class terminate_function; | 
|---|
| 745 |  | 
|---|
| 746 |     template< class ExceptionEvent > | 
|---|
| 747 |     detail::reaction_result handle_exception_event( | 
|---|
| 748 |       const ExceptionEvent & exceptionEvent, | 
|---|
| 749 |       state_base_type * pCurrentState ) | 
|---|
| 750 |     { | 
|---|
| 751 |       if ( terminated() ) | 
|---|
| 752 |       { | 
|---|
| 753 |         // there is no state that could handle the exception -> bail out | 
|---|
| 754 |         throw; | 
|---|
| 755 |       } | 
|---|
| 756 |  | 
|---|
| 757 |       // If we are stable, an event handler has thrown. | 
|---|
| 758 |       // Otherwise, either a state constructor, a transition action or an exit | 
|---|
| 759 |       // function has thrown and the state machine is now in an invalid state. | 
|---|
| 760 |       // This situation can be resolved by the exception event handler | 
|---|
| 761 |       // function by orderly transiting to another state or terminating. | 
|---|
| 762 |       // As a result of this, the machine must not be unstable when this | 
|---|
| 763 |       // function is left. | 
|---|
| 764 |       state_base_type * const pOutermostUnstableState = | 
|---|
| 765 |         get_pointer( pOutermostUnstableState_ ); | 
|---|
| 766 |       state_base_type * const pHandlingState = pOutermostUnstableState == 0 ? | 
|---|
| 767 |         pCurrentState : pOutermostUnstableState; | 
|---|
| 768 |  | 
|---|
| 769 |       BOOST_ASSERT( pHandlingState != 0 ); | 
|---|
| 770 |  | 
|---|
| 771 |       // Setting a member variable to a special value for the duration of a | 
|---|
| 772 |       // call surely looks like a kludge (normally it should be a parameter of | 
|---|
| 773 |       // the call). However, in this case it is unavoidable because the call | 
|---|
| 774 |       // below could result in a call to user code where passing through an | 
|---|
| 775 |       // additional bool parameter is not acceptable. | 
|---|
| 776 |       performFullExit_ = false; | 
|---|
| 777 |       const detail::reaction_result reactionResult = pHandlingState->react_impl( | 
|---|
| 778 |         exceptionEvent, exceptionEvent.dynamic_type() ); | 
|---|
| 779 |       // If the above call throws then performFullExit_ will obviously not be | 
|---|
| 780 |       // set back to true. In this case the termination triggered by the | 
|---|
| 781 |       // scope guard further up in the call stack will take care of this. | 
|---|
| 782 |       performFullExit_ = true; | 
|---|
| 783 |  | 
|---|
| 784 |       if ( ( reactionResult != detail::do_discard_event ) || | 
|---|
| 785 |         ( get_pointer( pOutermostUnstableState_ ) != 0 ) ) | 
|---|
| 786 |       { | 
|---|
| 787 |         throw; | 
|---|
| 788 |       } | 
|---|
| 789 |  | 
|---|
| 790 |       return detail::do_discard_event; | 
|---|
| 791 |     } | 
|---|
| 792 |  | 
|---|
| 793 |     class exception_event_handler | 
|---|
| 794 |     { | 
|---|
| 795 |       public: | 
|---|
| 796 |         ////////////////////////////////////////////////////////////////////// | 
|---|
| 797 |         exception_event_handler( | 
|---|
| 798 |           state_machine & machine, | 
|---|
| 799 |           state_base_type * pCurrentState = 0 | 
|---|
| 800 |         ) : | 
|---|
| 801 |           machine_( machine ), | 
|---|
| 802 |           pCurrentState_( pCurrentState ) | 
|---|
| 803 |         { | 
|---|
| 804 |         } | 
|---|
| 805 |  | 
|---|
| 806 |         template< class ExceptionEvent > | 
|---|
| 807 |         result operator()( | 
|---|
| 808 |           const ExceptionEvent & exceptionEvent ) | 
|---|
| 809 |         { | 
|---|
| 810 |           return detail::result_utility::make_result( | 
|---|
| 811 |             machine_.handle_exception_event( | 
|---|
| 812 |               exceptionEvent, pCurrentState_ ) ); | 
|---|
| 813 |         } | 
|---|
| 814 |  | 
|---|
| 815 |       private: | 
|---|
| 816 |         ////////////////////////////////////////////////////////////////////// | 
|---|
| 817 |         state_machine & machine_; | 
|---|
| 818 |         state_base_type * pCurrentState_; | 
|---|
| 819 |     }; | 
|---|
| 820 |     friend class exception_event_handler; | 
|---|
| 821 |  | 
|---|
| 822 |     class terminator | 
|---|
| 823 |     { | 
|---|
| 824 |       public: | 
|---|
| 825 |         terminator( state_machine & machine ) : | 
|---|
| 826 |           machine_( machine ), dismissed_( false ) {} | 
|---|
| 827 |         ~terminator() | 
|---|
| 828 |         { | 
|---|
| 829 |           if ( !dismissed_ ) { machine_.terminate_impl( false ); } | 
|---|
| 830 |         } | 
|---|
| 831 |         void dismiss() { dismissed_ = true; } | 
|---|
| 832 |  | 
|---|
| 833 |       private: | 
|---|
| 834 |         state_machine & machine_; | 
|---|
| 835 |         bool dismissed_; | 
|---|
| 836 |     }; | 
|---|
| 837 |     friend class terminator; | 
|---|
| 838 |  | 
|---|
| 839 |  | 
|---|
| 840 |     void send_event( const event_base_type & evt ) | 
|---|
| 841 |     { | 
|---|
| 842 |       terminator guard( *this ); | 
|---|
| 843 |       BOOST_ASSERT( get_pointer( pOutermostUnstableState_ ) == 0 ); | 
|---|
| 844 |       const typename rtti_policy_type::id_type eventType = evt.dynamic_type(); | 
|---|
| 845 |       detail::reaction_result reactionResult = detail::do_forward_event; | 
|---|
| 846 |        | 
|---|
| 847 |       for ( | 
|---|
| 848 |         typename state_list_type::iterator pState = currentStates_.begin(); | 
|---|
| 849 |         ( reactionResult == detail::do_forward_event ) && | 
|---|
| 850 |           ( pState != currentStatesEnd_ ); | 
|---|
| 851 |         ++pState ) | 
|---|
| 852 |       { | 
|---|
| 853 |         // CAUTION: The following statement could modify our state list! | 
|---|
| 854 |         // We must not continue iterating if the event was consumed | 
|---|
| 855 |         reactionResult = detail::result_utility::get_result( translator_( | 
|---|
| 856 |           detail::send_function< | 
|---|
| 857 |             state_base_type, event_base_type, rtti_policy_type::id_type >( | 
|---|
| 858 |               **pState, evt, eventType ), | 
|---|
| 859 |           exception_event_handler( *this, get_pointer( *pState ) ) ) ); | 
|---|
| 860 |       } | 
|---|
| 861 |  | 
|---|
| 862 |       guard.dismiss(); | 
|---|
| 863 |  | 
|---|
| 864 |       if ( reactionResult == detail::do_forward_event ) | 
|---|
| 865 |       { | 
|---|
| 866 |         polymorphic_downcast< MostDerived * >( this )->unconsumed_event( evt ); | 
|---|
| 867 |       } | 
|---|
| 868 |     } | 
|---|
| 869 |  | 
|---|
| 870 |  | 
|---|
| 871 |     void process_queued_events() | 
|---|
| 872 |     { | 
|---|
| 873 |       while ( !eventQueue_.empty() ) | 
|---|
| 874 |       { | 
|---|
| 875 |         const event_base_ptr_type pCurrentEvent( eventQueue_.front() ); | 
|---|
| 876 |         eventQueue_.pop_front(); | 
|---|
| 877 |         send_event( *pCurrentEvent ); | 
|---|
| 878 |       } | 
|---|
| 879 |     } | 
|---|
| 880 |  | 
|---|
| 881 |  | 
|---|
| 882 |     void terminate_impl( bool performFullExit ) | 
|---|
| 883 |     { | 
|---|
| 884 |       performFullExit_ = true; | 
|---|
| 885 |  | 
|---|
| 886 |       if ( !terminated() ) | 
|---|
| 887 |       { | 
|---|
| 888 |         // this also empties deferredMap_ | 
|---|
| 889 |         terminate_impl( *pOutermostState_, performFullExit ); | 
|---|
| 890 |       } | 
|---|
| 891 |  | 
|---|
| 892 |       eventQueue_.clear(); | 
|---|
| 893 |       shallowHistoryMap_.clear(); | 
|---|
| 894 |       deepHistoryMap_.clear(); | 
|---|
| 895 |     } | 
|---|
| 896 |  | 
|---|
| 897 |     void terminate_impl( state_base_type & theState, bool performFullExit ) | 
|---|
| 898 |     { | 
|---|
| 899 |       isInnermostCommonOuter_ = false; | 
|---|
| 900 |  | 
|---|
| 901 |       // If pOutermostUnstableState_ == 0, we know for sure that | 
|---|
| 902 |       // currentStates_.size() > 0, otherwise theState couldn't be alive any | 
|---|
| 903 |       // more | 
|---|
| 904 |       if ( get_pointer( pOutermostUnstableState_ ) != 0 ) | 
|---|
| 905 |       { | 
|---|
| 906 |         theState.remove_from_state_list( | 
|---|
| 907 |           currentStatesEnd_, pOutermostUnstableState_, performFullExit ); | 
|---|
| 908 |       } | 
|---|
| 909 |       // Optimization: We want to find out whether currentStates_ has size 1 | 
|---|
| 910 |       // and if yes use the optimized implementation below. Since | 
|---|
| 911 |       // list<>::size() is implemented quite inefficiently in some std libs | 
|---|
| 912 |       // it is best to just decrement the currentStatesEnd_ here and | 
|---|
| 913 |       // increment it again, if the test failed. | 
|---|
| 914 |       else if ( currentStates_.begin() == --currentStatesEnd_ ) | 
|---|
| 915 |       { | 
|---|
| 916 |         // The machine is stable and there is exactly one innermost state. | 
|---|
| 917 |         // The following optimization is only correct for a stable machine | 
|---|
| 918 |         // without orthogonal regions. | 
|---|
| 919 |         leaf_state_ptr_type & pState = *currentStatesEnd_; | 
|---|
| 920 |         pState->exit_impl( | 
|---|
| 921 |           pState, pOutermostUnstableState_, performFullExit ); | 
|---|
| 922 |       } | 
|---|
| 923 |       else | 
|---|
| 924 |       { | 
|---|
| 925 |         BOOST_ASSERT( currentStates_.size() > 1 ); | 
|---|
| 926 |         // The machine is stable and there are multiple innermost states | 
|---|
| 927 |         theState.remove_from_state_list( | 
|---|
| 928 |           ++currentStatesEnd_, pOutermostUnstableState_, performFullExit ); | 
|---|
| 929 |       } | 
|---|
| 930 |     } | 
|---|
| 931 |  | 
|---|
| 932 |  | 
|---|
| 933 |     node_state_base_ptr_type add_impl( | 
|---|
| 934 |       const leaf_state_ptr_type & pState, | 
|---|
| 935 |       detail::leaf_state< allocator_type, rtti_policy_type > & ) | 
|---|
| 936 |     { | 
|---|
| 937 |       if ( currentStatesEnd_ == currentStates_.end() ) | 
|---|
| 938 |       { | 
|---|
| 939 |         pState->set_list_position(  | 
|---|
| 940 |           currentStates_.insert( currentStatesEnd_, pState ) ); | 
|---|
| 941 |       } | 
|---|
| 942 |       else | 
|---|
| 943 |       { | 
|---|
| 944 |         *currentStatesEnd_ = pState; | 
|---|
| 945 |         pState->set_list_position( currentStatesEnd_ ); | 
|---|
| 946 |         ++currentStatesEnd_; | 
|---|
| 947 |       } | 
|---|
| 948 |  | 
|---|
| 949 |       return 0; | 
|---|
| 950 |     } | 
|---|
| 951 |  | 
|---|
| 952 |     node_state_base_ptr_type add_impl( | 
|---|
| 953 |       const node_state_base_ptr_type & pState, | 
|---|
| 954 |       state_base_type & ) | 
|---|
| 955 |     { | 
|---|
| 956 |       return pState; | 
|---|
| 957 |     } | 
|---|
| 958 |  | 
|---|
| 959 |     template< class State > | 
|---|
| 960 |     static bool is_in_highest_orthogonal_region() | 
|---|
| 961 |     { | 
|---|
| 962 |       return mpl::equal_to< | 
|---|
| 963 |         typename State::orthogonal_position, | 
|---|
| 964 |         mpl::minus<  | 
|---|
| 965 |           typename State::context_type::no_of_orthogonal_regions, | 
|---|
| 966 |           mpl::integral_c< detail::orthogonal_position_type, 1 > > | 
|---|
| 967 |       >::value; | 
|---|
| 968 |     } | 
|---|
| 969 |  | 
|---|
| 970 |  | 
|---|
| 971 |     typedef detail::history_key< rtti_policy_type > history_key_type; | 
|---|
| 972 |  | 
|---|
| 973 |     typedef std::map< | 
|---|
| 974 |       history_key_type, void (*)(), | 
|---|
| 975 |       std::less< history_key_type >, | 
|---|
| 976 |       typename boost::detail::allocator::rebind_to< | 
|---|
| 977 |         allocator_type, std::pair< const history_key_type, void (*)() > | 
|---|
| 978 |       >::type | 
|---|
| 979 |     > history_map_type; | 
|---|
| 980 |  | 
|---|
| 981 |     void store_history_impl( | 
|---|
| 982 |       history_map_type & historyMap, | 
|---|
| 983 |       const history_key_type & historyId, | 
|---|
| 984 |       void (*pConstructFunction)() ) | 
|---|
| 985 |     { | 
|---|
| 986 |       historyMap[ historyId ] = pConstructFunction; | 
|---|
| 987 |     } | 
|---|
| 988 |  | 
|---|
| 989 |     template< class DefaultState > | 
|---|
| 990 |     void construct_with_history_impl( | 
|---|
| 991 |       history_map_type & historyMap, | 
|---|
| 992 |       const typename DefaultState::context_ptr_type & pContext ) | 
|---|
| 993 |     { | 
|---|
| 994 |       typename history_map_type::iterator pFoundSlot = historyMap.find( | 
|---|
| 995 |         history_key_type::make_history_key< DefaultState >() ); | 
|---|
| 996 |        | 
|---|
| 997 |       if ( ( pFoundSlot == historyMap.end() ) || ( pFoundSlot->second == 0 ) ) | 
|---|
| 998 |       { | 
|---|
| 999 |         // We have never entered this state before or history was cleared | 
|---|
| 1000 |         DefaultState::deep_construct( | 
|---|
| 1001 |           pContext, *polymorphic_downcast< MostDerived * >( this ) ); | 
|---|
| 1002 |       } | 
|---|
| 1003 |       else | 
|---|
| 1004 |       { | 
|---|
| 1005 |         typedef void construct_function( | 
|---|
| 1006 |           const typename DefaultState::context_ptr_type &, | 
|---|
| 1007 |           typename DefaultState::outermost_context_base_type & ); | 
|---|
| 1008 |         // 5.2.10.6 declares that reinterpret_casting a function pointer to a | 
|---|
| 1009 |         // different function pointer and back must yield the same value. The | 
|---|
| 1010 |         // following reinterpret_cast is the second half of such a sequence. | 
|---|
| 1011 |         construct_function * const pConstructFunction = | 
|---|
| 1012 |           reinterpret_cast< construct_function * >( pFoundSlot->second ); | 
|---|
| 1013 |         (*pConstructFunction)( | 
|---|
| 1014 |           pContext, *polymorphic_downcast< MostDerived * >( this ) ); | 
|---|
| 1015 |       } | 
|---|
| 1016 |     } | 
|---|
| 1017 |  | 
|---|
| 1018 |     typedef std::list< | 
|---|
| 1019 |       event_base_ptr_type, | 
|---|
| 1020 |       typename boost::detail::allocator::rebind_to< | 
|---|
| 1021 |         allocator_type, event_base_ptr_type >::type | 
|---|
| 1022 |     > event_queue_type; | 
|---|
| 1023 |  | 
|---|
| 1024 |     typedef std::map< | 
|---|
| 1025 |       const state_base_type *, event_queue_type, | 
|---|
| 1026 |       std::less< const state_base_type * >, | 
|---|
| 1027 |       typename boost::detail::allocator::rebind_to< | 
|---|
| 1028 |         allocator_type, | 
|---|
| 1029 |         std::pair< const state_base_type * const, event_queue_type > | 
|---|
| 1030 |       >::type | 
|---|
| 1031 |     > deferred_map_type; | 
|---|
| 1032 |  | 
|---|
| 1033 |  | 
|---|
| 1034 |     event_queue_type eventQueue_; | 
|---|
| 1035 |     deferred_map_type deferredMap_; | 
|---|
| 1036 |     state_list_type currentStates_; | 
|---|
| 1037 |     typename state_list_type::iterator currentStatesEnd_; | 
|---|
| 1038 |     state_base_type * pOutermostState_; | 
|---|
| 1039 |     bool isInnermostCommonOuter_; | 
|---|
| 1040 |     node_state_base_ptr_type pOutermostUnstableState_; | 
|---|
| 1041 |     ExceptionTranslator translator_; | 
|---|
| 1042 |     bool performFullExit_; | 
|---|
| 1043 |     history_map_type shallowHistoryMap_; | 
|---|
| 1044 |     history_map_type deepHistoryMap_; | 
|---|
| 1045 | }; | 
|---|
| 1046 |  | 
|---|
| 1047 |  | 
|---|
| 1048 |  | 
|---|
| 1049 | } // namespace statechart | 
|---|
| 1050 | } // namespace boost | 
|---|
| 1051 |  | 
|---|
| 1052 |  | 
|---|
| 1053 |  | 
|---|
| 1054 | #endif | 
|---|