annotate DEPENDENCIES/generic/include/boost/statechart/simple_state.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 #ifndef BOOST_STATECHART_SIMPLE_STATE_HPP_INCLUDED
Chris@16 2 #define BOOST_STATECHART_SIMPLE_STATE_HPP_INCLUDED
Chris@16 3 //////////////////////////////////////////////////////////////////////////////
Chris@16 4 // Copyright 2002-2010 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/event.hpp>
Chris@16 12
Chris@16 13 #include <boost/statechart/detail/leaf_state.hpp>
Chris@16 14 #include <boost/statechart/detail/node_state.hpp>
Chris@16 15 #include <boost/statechart/detail/constructor.hpp>
Chris@16 16 #include <boost/statechart/detail/memory.hpp>
Chris@16 17
Chris@16 18 #include <boost/mpl/eval_if.hpp>
Chris@16 19 #include <boost/mpl/if.hpp>
Chris@16 20 #include <boost/mpl/identity.hpp>
Chris@16 21 #include <boost/mpl/is_sequence.hpp>
Chris@16 22 #include <boost/mpl/list.hpp>
Chris@16 23 #include <boost/mpl/empty.hpp>
Chris@16 24 #include <boost/mpl/size.hpp>
Chris@16 25 #include <boost/mpl/front.hpp>
Chris@16 26 #include <boost/mpl/at.hpp>
Chris@16 27 #include <boost/mpl/find.hpp>
Chris@16 28 #include <boost/mpl/find_if.hpp>
Chris@16 29 #include <boost/mpl/contains.hpp>
Chris@16 30 #include <boost/mpl/distance.hpp>
Chris@16 31 #include <boost/mpl/deref.hpp>
Chris@16 32 #include <boost/mpl/pop_front.hpp>
Chris@16 33 #include <boost/mpl/push_front.hpp>
Chris@16 34 #include <boost/mpl/clear.hpp>
Chris@16 35 #include <boost/mpl/placeholders.hpp>
Chris@16 36 #include <boost/mpl/bool.hpp>
Chris@16 37 #include <boost/mpl/integral_c.hpp>
Chris@16 38 #include <boost/mpl/less.hpp>
Chris@16 39 #include <boost/mpl/equal_to.hpp>
Chris@16 40 #include <boost/mpl/not.hpp>
Chris@16 41 #include <boost/mpl/or.hpp>
Chris@16 42
Chris@16 43 #include <boost/mpl/plus.hpp>
Chris@16 44 #include <boost/mpl/max_element.hpp>
Chris@16 45 #include <boost/mpl/greater.hpp>
Chris@16 46
Chris@16 47 #include <boost/get_pointer.hpp>
Chris@16 48 #include <boost/intrusive_ptr.hpp>
Chris@16 49 #include <boost/assert.hpp>
Chris@16 50 #include <boost/type_traits/is_base_of.hpp>
Chris@16 51 #include <boost/type_traits/is_same.hpp>
Chris@16 52 #include <boost/static_assert.hpp>
Chris@101 53 #include <boost/polymorphic_cast.hpp> // boost::polymorphic_downcast
Chris@16 54
Chris@16 55 #include <cstddef> // std::size_t
Chris@16 56
Chris@16 57
Chris@16 58
Chris@16 59 namespace boost
Chris@16 60 {
Chris@16 61 namespace statechart
Chris@16 62 {
Chris@16 63 namespace detail
Chris@16 64 {
Chris@16 65
Chris@16 66
Chris@16 67
Chris@16 68 //////////////////////////////////////////////////////////////////////////////
Chris@16 69 template< class T >
Chris@16 70 struct make_list : public mpl::eval_if<
Chris@16 71 mpl::is_sequence< T >,
Chris@16 72 mpl::identity< T >,
Chris@16 73 mpl::identity< mpl::list< T > > > {};
Chris@16 74
Chris@16 75 //////////////////////////////////////////////////////////////////////////////
Chris@16 76 template< class MostDerived, class Context, class InnerInitial >
Chris@16 77 struct simple_state_base_type
Chris@16 78 {
Chris@16 79 private:
Chris@16 80 typedef typename Context::outermost_context_base_type::allocator_type
Chris@16 81 allocator_type;
Chris@16 82 typedef typename Context::outermost_context_base_type::rtti_policy_type
Chris@16 83 rtti_policy_type;
Chris@16 84 typedef typename detail::make_list< InnerInitial >::type
Chris@16 85 inner_initial_list;
Chris@16 86 typedef typename mpl::size< inner_initial_list >::type
Chris@16 87 inner_initial_list_size;
Chris@16 88
Chris@16 89 public:
Chris@16 90 typedef typename mpl::eval_if<
Chris@16 91 mpl::empty< inner_initial_list >,
Chris@16 92 mpl::identity< typename rtti_policy_type::
Chris@16 93 template rtti_derived_type< MostDerived, leaf_state<
Chris@16 94 allocator_type,
Chris@16 95 rtti_policy_type > > >,
Chris@16 96 mpl::identity< typename rtti_policy_type::
Chris@16 97 template rtti_derived_type< MostDerived, node_state<
Chris@16 98 inner_initial_list_size,
Chris@16 99 allocator_type,
Chris@16 100 rtti_policy_type > > > >::type type;
Chris@16 101 };
Chris@16 102
Chris@16 103
Chris@16 104 //////////////////////////////////////////////////////////////////////////////
Chris@16 105 struct no_transition_function
Chris@16 106 {
Chris@16 107 template< class CommonContext >
Chris@16 108 void operator()( CommonContext & ) const {}
Chris@16 109 };
Chris@16 110
Chris@16 111 template< class TransitionContext, class Event >
Chris@16 112 class transition_function
Chris@16 113 {
Chris@16 114 public:
Chris@16 115 transition_function(
Chris@16 116 void ( TransitionContext::*pTransitionAction )( const Event & ),
Chris@16 117 const Event & evt
Chris@16 118 ) :
Chris@16 119 pTransitionAction_( pTransitionAction ),
Chris@16 120 evt_( evt )
Chris@16 121 {
Chris@16 122 }
Chris@16 123
Chris@16 124 template< class CommonContext >
Chris@16 125 void operator()( CommonContext & commonContext ) const
Chris@16 126 {
Chris@16 127 ( commonContext.template context< TransitionContext >()
Chris@16 128 .*pTransitionAction_ )( evt_ );
Chris@16 129 }
Chris@16 130
Chris@16 131 private:
Chris@16 132 // avoids C4512 (assignment operator could not be generated)
Chris@16 133 transition_function & operator=( const transition_function & );
Chris@16 134
Chris@16 135 void ( TransitionContext::*pTransitionAction_ )( const Event & );
Chris@16 136 const Event & evt_;
Chris@16 137 };
Chris@16 138
Chris@16 139
Chris@16 140 template< bool contextHasInheritedDeepHistory, bool contextHasDeepHistory >
Chris@16 141 struct deep_history_storer
Chris@16 142 {
Chris@16 143 template< class HistorizedState, class LeafState, class Context >
Chris@16 144 static void store_deep_history( Context & ) {}
Chris@16 145 };
Chris@16 146
Chris@16 147 template<>
Chris@16 148 struct deep_history_storer< true, false >
Chris@16 149 {
Chris@16 150 template< class HistorizedState, class LeafState, class Context >
Chris@16 151 static void store_deep_history( Context & ctx )
Chris@16 152 {
Chris@16 153 ctx.template store_deep_history_impl< LeafState >();
Chris@16 154 }
Chris@16 155 };
Chris@16 156
Chris@16 157 template<>
Chris@16 158 struct deep_history_storer< true, true >
Chris@16 159 {
Chris@16 160 template< class HistorizedState, class LeafState, class Context >
Chris@16 161 static void store_deep_history( Context & ctx )
Chris@16 162 {
Chris@16 163 ctx.outermost_context_base().template store_deep_history<
Chris@16 164 HistorizedState, LeafState >();
Chris@16 165 ctx.template store_deep_history_impl< LeafState >();
Chris@16 166 }
Chris@16 167 };
Chris@16 168
Chris@16 169
Chris@16 170
Chris@16 171 } // namespace detail
Chris@16 172
Chris@16 173
Chris@16 174
Chris@16 175 //////////////////////////////////////////////////////////////////////////////
Chris@16 176 enum history_mode
Chris@16 177 {
Chris@16 178 has_no_history,
Chris@16 179 has_shallow_history,
Chris@16 180 has_deep_history,
Chris@16 181 has_full_history // shallow & deep
Chris@16 182 };
Chris@16 183
Chris@16 184
Chris@16 185
Chris@16 186 //////////////////////////////////////////////////////////////////////////////
Chris@16 187 template< class MostDerived,
Chris@16 188 class Context,
Chris@16 189 class InnerInitial = mpl::list<>,
Chris@16 190 history_mode historyMode = has_no_history >
Chris@16 191 class simple_state : public detail::simple_state_base_type< MostDerived,
Chris@16 192 typename Context::inner_context_type, InnerInitial >::type
Chris@16 193 {
Chris@16 194 typedef typename detail::simple_state_base_type<
Chris@16 195 MostDerived, typename Context::inner_context_type,
Chris@16 196 InnerInitial >::type base_type;
Chris@16 197
Chris@16 198 public:
Chris@16 199 //////////////////////////////////////////////////////////////////////////
Chris@16 200 typedef mpl::list<> reactions;
Chris@16 201
Chris@16 202 typedef typename Context::inner_context_type context_type;
Chris@16 203
Chris@16 204 template< detail::orthogonal_position_type innerOrthogonalPosition >
Chris@16 205 struct orthogonal
Chris@16 206 {
Chris@16 207 typedef mpl::integral_c<
Chris@16 208 detail::orthogonal_position_type,
Chris@16 209 innerOrthogonalPosition > inner_orthogonal_position;
Chris@16 210 typedef MostDerived inner_context_type;
Chris@16 211 };
Chris@16 212
Chris@16 213 typedef typename context_type::outermost_context_type
Chris@16 214 outermost_context_type;
Chris@16 215
Chris@16 216 outermost_context_type & outermost_context()
Chris@16 217 {
Chris@16 218 // This assert fails when an attempt is made to access the state machine
Chris@16 219 // from a constructor of a state that is *not* a subtype of state<>.
Chris@16 220 // To correct this, derive from state<> instead of simple_state<>.
Chris@16 221 BOOST_ASSERT( get_pointer( pContext_ ) != 0 );
Chris@16 222 return pContext_->outermost_context();
Chris@16 223 }
Chris@16 224
Chris@16 225 const outermost_context_type & outermost_context() const
Chris@16 226 {
Chris@16 227 // This assert fails when an attempt is made to access the state machine
Chris@16 228 // from a constructor of a state that is *not* a subtype of state<>.
Chris@16 229 // To correct this, derive from state<> instead of simple_state<>.
Chris@16 230 BOOST_ASSERT( get_pointer( pContext_ ) != 0 );
Chris@16 231 return pContext_->outermost_context();
Chris@16 232 }
Chris@16 233
Chris@16 234 template< class OtherContext >
Chris@16 235 OtherContext & context()
Chris@16 236 {
Chris@16 237 typedef typename mpl::if_<
Chris@16 238 is_base_of< OtherContext, MostDerived >,
Chris@16 239 context_impl_this_context,
Chris@16 240 context_impl_other_context
Chris@16 241 >::type impl;
Chris@16 242 return impl::template context_impl< OtherContext >( *this );
Chris@16 243 }
Chris@16 244
Chris@16 245 template< class OtherContext >
Chris@16 246 const OtherContext & context() const
Chris@16 247 {
Chris@16 248 typedef typename mpl::if_<
Chris@16 249 is_base_of< OtherContext, MostDerived >,
Chris@16 250 context_impl_this_context,
Chris@16 251 context_impl_other_context
Chris@16 252 >::type impl;
Chris@16 253 return impl::template context_impl< OtherContext >( *this );
Chris@16 254 }
Chris@16 255
Chris@16 256 template< class Target >
Chris@16 257 Target state_cast() const
Chris@16 258 {
Chris@16 259 return outermost_context_base().template state_cast< Target >();
Chris@16 260 }
Chris@16 261
Chris@16 262 template< class Target >
Chris@16 263 Target state_downcast() const
Chris@16 264 {
Chris@16 265 return outermost_context_base().template state_downcast< Target >();
Chris@16 266 }
Chris@16 267
Chris@16 268 typedef typename context_type::state_base_type state_base_type;
Chris@16 269 typedef typename context_type::state_iterator state_iterator;
Chris@16 270
Chris@16 271 state_iterator state_begin() const
Chris@16 272 {
Chris@16 273 return outermost_context_base().state_begin();
Chris@16 274 }
Chris@16 275
Chris@16 276 state_iterator state_end() const
Chris@16 277 {
Chris@16 278 return outermost_context_base().state_end();
Chris@16 279 }
Chris@16 280
Chris@16 281
Chris@16 282 typedef typename context_type::event_base_ptr_type event_base_ptr_type;
Chris@16 283
Chris@16 284 void post_event( const event_base_ptr_type & pEvent )
Chris@16 285 {
Chris@16 286 outermost_context_base().post_event_impl( pEvent );
Chris@16 287 }
Chris@16 288
Chris@16 289 void post_event( const event_base & evt )
Chris@16 290 {
Chris@16 291 outermost_context_base().post_event_impl( evt );
Chris@16 292 }
Chris@16 293
Chris@16 294 result discard_event()
Chris@16 295 {
Chris@16 296 return detail::result_utility::make_result( detail::do_discard_event );
Chris@16 297 }
Chris@16 298
Chris@16 299 result forward_event()
Chris@16 300 {
Chris@16 301 return detail::result_utility::make_result( detail::do_forward_event );
Chris@16 302 }
Chris@16 303
Chris@16 304 result defer_event()
Chris@16 305 {
Chris@16 306 this->state_base_type::defer_event();
Chris@16 307 return detail::result_utility::make_result( detail::do_defer_event );
Chris@16 308 }
Chris@16 309
Chris@16 310 template< class DestinationState >
Chris@16 311 result transit()
Chris@16 312 {
Chris@16 313 return transit_impl< DestinationState, outermost_context_type >(
Chris@16 314 detail::no_transition_function() );
Chris@16 315 }
Chris@16 316
Chris@16 317 template< class DestinationState, class TransitionContext, class Event >
Chris@16 318 result transit(
Chris@16 319 void ( TransitionContext::*pTransitionAction )( const Event & ),
Chris@16 320 const Event & evt )
Chris@16 321 {
Chris@16 322 return transit_impl< DestinationState, TransitionContext >(
Chris@16 323 detail::transition_function< TransitionContext, Event >(
Chris@16 324 pTransitionAction, evt ) );
Chris@16 325 }
Chris@16 326
Chris@16 327 result terminate()
Chris@16 328 {
Chris@16 329 outermost_context_base().terminate_as_reaction( *this );
Chris@16 330 return detail::result_utility::make_result( detail::do_discard_event );
Chris@16 331 }
Chris@16 332
Chris@16 333 template<
Chris@16 334 class HistoryContext,
Chris@16 335 detail::orthogonal_position_type orthogonalPosition >
Chris@16 336 void clear_shallow_history()
Chris@16 337 {
Chris@16 338 outermost_context_base().template clear_shallow_history<
Chris@16 339 HistoryContext, orthogonalPosition >();
Chris@16 340 }
Chris@16 341
Chris@16 342 template<
Chris@16 343 class HistoryContext,
Chris@16 344 detail::orthogonal_position_type orthogonalPosition >
Chris@16 345 void clear_deep_history()
Chris@16 346 {
Chris@16 347 outermost_context_base().template clear_deep_history<
Chris@16 348 HistoryContext, orthogonalPosition >();
Chris@16 349 }
Chris@16 350
Chris@16 351 const event_base * triggering_event() const
Chris@16 352 {
Chris@16 353 return outermost_context_base().triggering_event();
Chris@16 354 }
Chris@16 355
Chris@16 356 protected:
Chris@16 357 //////////////////////////////////////////////////////////////////////////
Chris@16 358 simple_state() : pContext_( 0 ) {}
Chris@16 359
Chris@16 360 ~simple_state()
Chris@16 361 {
Chris@16 362 // As a result of a throwing derived class constructor, this destructor
Chris@16 363 // can be called before the context is set.
Chris@16 364 if ( get_pointer( pContext_ ) != 0 )
Chris@16 365 {
Chris@16 366 if ( this->deferred_events() )
Chris@16 367 {
Chris@16 368 outermost_context_base().release_events();
Chris@16 369 }
Chris@16 370
Chris@16 371 pContext_->remove_inner_state( orthogonal_position::value );
Chris@16 372 }
Chris@16 373 }
Chris@16 374
Chris@16 375 public:
Chris@16 376 //////////////////////////////////////////////////////////////////////////
Chris@16 377 // The following declarations should be private.
Chris@16 378 // They are only public because many compilers lack template friends.
Chris@16 379 //////////////////////////////////////////////////////////////////////////
Chris@16 380 typedef typename Context::inner_orthogonal_position orthogonal_position;
Chris@16 381
Chris@16 382 // If you receive a
Chris@16 383 // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or similar
Chris@16 384 // compiler error here then either this state resides in a non-existent
Chris@16 385 // orthogonal region of the outer state or the outer state does not have
Chris@16 386 // inner states.
Chris@16 387 BOOST_STATIC_ASSERT( ( mpl::less<
Chris@16 388 orthogonal_position,
Chris@16 389 typename context_type::no_of_orthogonal_regions >::value ) );
Chris@16 390
Chris@16 391 typedef MostDerived inner_context_type;
Chris@16 392 typedef mpl::integral_c< detail::orthogonal_position_type, 0 >
Chris@16 393 inner_orthogonal_position;
Chris@16 394
Chris@16 395 typedef typename context_type::event_base_type event_base_type;
Chris@16 396 typedef typename context_type::rtti_policy_type rtti_policy_type;
Chris@16 397
Chris@16 398 typedef typename context_type::outermost_context_base_type
Chris@16 399 outermost_context_base_type;
Chris@16 400 typedef typename context_type::inner_context_ptr_type context_ptr_type;
Chris@16 401 typedef typename context_type::state_list_type state_list_type;
Chris@16 402 typedef intrusive_ptr< inner_context_type > inner_context_ptr_type;
Chris@16 403 typedef typename detail::make_list< InnerInitial >::type
Chris@16 404 inner_initial_list;
Chris@16 405 typedef typename mpl::size< inner_initial_list >::type
Chris@16 406 inner_initial_list_size;
Chris@16 407 typedef mpl::integral_c<
Chris@16 408 detail::orthogonal_position_type,
Chris@16 409 inner_initial_list_size::value > no_of_orthogonal_regions;
Chris@16 410 typedef typename mpl::push_front<
Chris@16 411 typename context_type::context_type_list,
Chris@16 412 context_type >::type context_type_list;
Chris@16 413
Chris@16 414 // If you receive a
Chris@16 415 // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or similar
Chris@16 416 // compiler error here then the direct or indirect context of this state
Chris@16 417 // has deep history _and_ this state has two or more orthogonal regions.
Chris@16 418 // Boost.Statechart does not currently support deep history in a state whose
Chris@16 419 // direct or indirect inner states have two or more orthogonal regions.
Chris@16 420 // Please consult the documentation on how to work around this limitation.
Chris@16 421 BOOST_STATIC_ASSERT( ( mpl::or_<
Chris@16 422 mpl::less<
Chris@16 423 no_of_orthogonal_regions,
Chris@16 424 mpl::integral_c< detail::orthogonal_position_type, 2 > >,
Chris@16 425 mpl::not_<
Chris@16 426 typename context_type::inherited_deep_history > >::value ) );
Chris@16 427
Chris@16 428 typedef mpl::bool_< ( historyMode & has_shallow_history ) != 0 >
Chris@16 429 shallow_history;
Chris@16 430 typedef typename context_type::shallow_history stores_shallow_history;
Chris@16 431
Chris@16 432 typedef mpl::bool_< ( historyMode & has_deep_history ) != 0 >
Chris@16 433 deep_history;
Chris@16 434 typedef typename mpl::or_<
Chris@16 435 deep_history,
Chris@16 436 typename context_type::inherited_deep_history
Chris@16 437 >::type inherited_deep_history;
Chris@16 438 typedef typename mpl::and_<
Chris@16 439 inherited_deep_history,
Chris@16 440 mpl::empty< inner_initial_list > >::type stores_deep_history;
Chris@16 441
Chris@16 442 void * operator new( std::size_t size )
Chris@16 443 {
Chris@16 444 return detail::allocate< MostDerived,
Chris@16 445 typename outermost_context_type::allocator_type >( size );
Chris@16 446 }
Chris@16 447
Chris@16 448 void operator delete( void * pState )
Chris@16 449 {
Chris@16 450 detail::deallocate< MostDerived,
Chris@16 451 typename outermost_context_type::allocator_type >( pState );
Chris@16 452 }
Chris@16 453
Chris@16 454 outermost_context_base_type & outermost_context_base()
Chris@16 455 {
Chris@16 456 // This assert fails when an attempt is made to access the state machine
Chris@16 457 // from a constructor of a state that is *not* a subtype of state<>.
Chris@16 458 // To correct this, derive from state<> instead of simple_state<>.
Chris@16 459 BOOST_ASSERT( get_pointer( pContext_ ) != 0 );
Chris@16 460 return pContext_->outermost_context_base();
Chris@16 461 }
Chris@16 462
Chris@16 463 const outermost_context_base_type & outermost_context_base() const
Chris@16 464 {
Chris@16 465 // This assert fails when an attempt is made to access the state machine
Chris@16 466 // from a constructor of a state that is *not* a subtype of state<>.
Chris@16 467 // To correct this, derive from state<> instead of simple_state<>.
Chris@16 468 BOOST_ASSERT( get_pointer( pContext_ ) != 0 );
Chris@16 469 return pContext_->outermost_context_base();
Chris@16 470 }
Chris@16 471
Chris@16 472 virtual const state_base_type * outer_state_ptr() const
Chris@16 473 {
Chris@16 474 typedef typename mpl::if_<
Chris@16 475 is_same< outermost_context_type, context_type >,
Chris@16 476 outer_state_ptr_impl_outermost,
Chris@16 477 outer_state_ptr_impl_non_outermost
Chris@16 478 >::type impl;
Chris@16 479 return impl::outer_state_ptr_impl( *this );
Chris@16 480 }
Chris@16 481
Chris@16 482 virtual detail::reaction_result react_impl(
Chris@16 483 const event_base_type & evt,
Chris@16 484 typename rtti_policy_type::id_type eventType )
Chris@16 485 {
Chris@16 486 typedef typename detail::make_list<
Chris@16 487 typename MostDerived::reactions >::type reaction_list;
Chris@16 488 detail::reaction_result reactionResult =
Chris@16 489 local_react< reaction_list >( evt, eventType );
Chris@16 490
Chris@16 491 // At this point we can only safely access pContext_ if the handler did
Chris@16 492 // not return do_discard_event!
Chris@16 493 if ( reactionResult == detail::do_forward_event )
Chris@16 494 {
Chris@16 495 // TODO: The following call to react_impl of our outer state should
Chris@16 496 // be made with a context_type:: prefix to call directly instead of
Chris@16 497 // virtually. For some reason the compiler complains...
Chris@16 498 reactionResult = pContext_->react_impl( evt, eventType );
Chris@16 499 }
Chris@16 500
Chris@16 501 return reactionResult;
Chris@16 502 }
Chris@16 503
Chris@16 504 virtual void exit_impl(
Chris@16 505 typename base_type::direct_state_base_ptr_type & pSelf,
Chris@16 506 typename state_base_type::node_state_base_ptr_type &
Chris@16 507 pOutermostUnstableState,
Chris@16 508 bool performFullExit )
Chris@16 509 {
Chris@16 510 inner_context_ptr_type pMostDerivedSelf =
Chris@16 511 polymorphic_downcast< MostDerived * >( this );
Chris@16 512 pSelf = 0;
Chris@16 513 exit_impl( pMostDerivedSelf, pOutermostUnstableState, performFullExit );
Chris@16 514 }
Chris@16 515
Chris@16 516 void exit_impl(
Chris@16 517 inner_context_ptr_type & pSelf,
Chris@16 518 typename state_base_type::node_state_base_ptr_type &
Chris@16 519 pOutermostUnstableState,
Chris@16 520 bool performFullExit )
Chris@16 521 {
Chris@16 522 switch ( this->ref_count() )
Chris@16 523 {
Chris@16 524 case 2:
Chris@16 525 if ( get_pointer( pOutermostUnstableState ) ==
Chris@16 526 static_cast< state_base_type * >( this ) )
Chris@16 527 {
Chris@16 528 pContext_->set_outermost_unstable_state(
Chris@16 529 pOutermostUnstableState );
Chris@101 530 BOOST_FALLTHROUGH;
Chris@16 531 }
Chris@16 532 else
Chris@16 533 {
Chris@16 534 break;
Chris@16 535 }
Chris@16 536 case 1:
Chris@16 537 {
Chris@16 538 if ( get_pointer( pOutermostUnstableState ) == 0 )
Chris@16 539 {
Chris@16 540 pContext_->set_outermost_unstable_state(
Chris@16 541 pOutermostUnstableState );
Chris@16 542 }
Chris@16 543
Chris@16 544 if ( performFullExit )
Chris@16 545 {
Chris@16 546 pSelf->exit();
Chris@16 547 check_store_shallow_history< stores_shallow_history >();
Chris@16 548 check_store_deep_history< stores_deep_history >();
Chris@16 549 }
Chris@16 550
Chris@16 551 context_ptr_type pContext = pContext_;
Chris@16 552 pSelf = 0;
Chris@16 553 pContext->exit_impl(
Chris@16 554 pContext, pOutermostUnstableState, performFullExit );
Chris@16 555 break;
Chris@16 556 }
Chris@16 557 default:
Chris@16 558 break;
Chris@16 559 }
Chris@16 560 }
Chris@16 561
Chris@16 562 void set_outermost_unstable_state(
Chris@16 563 typename state_base_type::node_state_base_ptr_type &
Chris@16 564 pOutermostUnstableState )
Chris@16 565 {
Chris@16 566 pOutermostUnstableState = this;
Chris@16 567 }
Chris@16 568
Chris@16 569 template< class OtherContext >
Chris@16 570 const typename OtherContext::inner_context_ptr_type & context_ptr() const
Chris@16 571 {
Chris@16 572 typedef typename mpl::if_<
Chris@16 573 is_same< OtherContext, context_type >,
Chris@16 574 context_ptr_impl_my_context,
Chris@16 575 context_ptr_impl_other_context
Chris@16 576 >::type impl;
Chris@16 577
Chris@16 578 return impl::template context_ptr_impl< OtherContext >( *this );
Chris@16 579 }
Chris@16 580
Chris@16 581 static void initial_deep_construct(
Chris@16 582 outermost_context_base_type & outermostContextBase )
Chris@16 583 {
Chris@16 584 deep_construct( &outermostContextBase, outermostContextBase );
Chris@16 585 }
Chris@16 586
Chris@16 587 static void deep_construct(
Chris@16 588 const context_ptr_type & pContext,
Chris@16 589 outermost_context_base_type & outermostContextBase )
Chris@16 590 {
Chris@16 591 const inner_context_ptr_type pInnerContext(
Chris@16 592 shallow_construct( pContext, outermostContextBase ) );
Chris@16 593 deep_construct_inner< inner_initial_list >(
Chris@16 594 pInnerContext, outermostContextBase );
Chris@16 595 }
Chris@16 596
Chris@16 597 static inner_context_ptr_type shallow_construct(
Chris@16 598 const context_ptr_type & pContext,
Chris@16 599 outermost_context_base_type & outermostContextBase )
Chris@16 600 {
Chris@16 601 const inner_context_ptr_type pInnerContext( new MostDerived );
Chris@16 602 pInnerContext->set_context( pContext );
Chris@16 603 outermostContextBase.add( pInnerContext );
Chris@16 604 return pInnerContext;
Chris@16 605 }
Chris@16 606
Chris@16 607 void set_context( const context_ptr_type & pContext )
Chris@16 608 {
Chris@16 609 BOOST_ASSERT( get_pointer( pContext ) != 0 );
Chris@16 610 pContext_ = pContext;
Chris@16 611 base_type::set_context(
Chris@16 612 orthogonal_position::value, get_pointer( pContext ) );
Chris@16 613 }
Chris@16 614
Chris@16 615 template< class InnerList >
Chris@16 616 static void deep_construct_inner(
Chris@16 617 const inner_context_ptr_type & pInnerContext,
Chris@16 618 outermost_context_base_type & outermostContextBase )
Chris@16 619 {
Chris@16 620 typedef typename mpl::if_<
Chris@16 621 mpl::empty< InnerList >,
Chris@16 622 deep_construct_inner_impl_empty,
Chris@16 623 deep_construct_inner_impl_non_empty
Chris@16 624 >::type impl;
Chris@16 625 impl::template deep_construct_inner_impl< InnerList >(
Chris@16 626 pInnerContext, outermostContextBase );
Chris@16 627 }
Chris@16 628
Chris@16 629 template< class LeafState >
Chris@16 630 void store_deep_history_impl()
Chris@16 631 {
Chris@16 632 detail::deep_history_storer<
Chris@16 633 context_type::inherited_deep_history::value,
Chris@16 634 context_type::deep_history::value
Chris@16 635 >::template store_deep_history< MostDerived, LeafState >(
Chris@16 636 *pContext_ );
Chris@16 637 }
Chris@16 638
Chris@16 639 private:
Chris@16 640 //////////////////////////////////////////////////////////////////////////
Chris@16 641 struct context_ptr_impl_other_context
Chris@16 642 {
Chris@16 643 template< class OtherContext, class State >
Chris@16 644 static const typename OtherContext::inner_context_ptr_type &
Chris@16 645 context_ptr_impl( const State & stt )
Chris@16 646 {
Chris@16 647 // This assert fails when an attempt is made to access an outer
Chris@16 648 // context from a constructor of a state that is *not* a subtype of
Chris@16 649 // state<>. To correct this, derive from state<> instead of
Chris@16 650 // simple_state<>.
Chris@16 651 BOOST_ASSERT( get_pointer( stt.pContext_ ) != 0 );
Chris@16 652 return stt.pContext_->template context_ptr< OtherContext >();
Chris@16 653 }
Chris@16 654 };
Chris@16 655 friend struct context_ptr_impl_other_context;
Chris@16 656
Chris@16 657 struct context_ptr_impl_my_context
Chris@16 658 {
Chris@16 659 template< class OtherContext, class State >
Chris@16 660 static const typename OtherContext::inner_context_ptr_type &
Chris@16 661 context_ptr_impl( const State & stt )
Chris@16 662 {
Chris@16 663 // This assert fails when an attempt is made to access an outer
Chris@16 664 // context from a constructor of a state that is *not* a subtype of
Chris@16 665 // state<>. To correct this, derive from state<> instead of
Chris@16 666 // simple_state<>.
Chris@16 667 BOOST_ASSERT( get_pointer( stt.pContext_ ) != 0 );
Chris@16 668 return stt.pContext_;
Chris@16 669 }
Chris@16 670 };
Chris@16 671 friend struct context_ptr_impl_my_context;
Chris@16 672
Chris@16 673 struct context_impl_other_context
Chris@16 674 {
Chris@16 675 template< class OtherContext, class State >
Chris@16 676 static OtherContext & context_impl( State & stt )
Chris@16 677 {
Chris@16 678 // This assert fails when an attempt is made to access an outer
Chris@16 679 // context from a constructor of a state that is *not* a subtype of
Chris@16 680 // state<>. To correct this, derive from state<> instead of
Chris@16 681 // simple_state<>.
Chris@16 682 BOOST_ASSERT( get_pointer( stt.pContext_ ) != 0 );
Chris@16 683 return stt.pContext_->template context< OtherContext >();
Chris@16 684 }
Chris@16 685 };
Chris@16 686 friend struct context_impl_other_context;
Chris@16 687
Chris@16 688 struct context_impl_this_context
Chris@16 689 {
Chris@16 690 template< class OtherContext, class State >
Chris@16 691 static OtherContext & context_impl( State & stt )
Chris@16 692 {
Chris@16 693 return *polymorphic_downcast< MostDerived * >( &stt );
Chris@16 694 }
Chris@16 695 };
Chris@16 696 friend struct context_impl_this_context;
Chris@16 697
Chris@16 698 template< class DestinationState,
Chris@16 699 class TransitionContext,
Chris@16 700 class TransitionAction >
Chris@16 701 result transit_impl( const TransitionAction & transitionAction )
Chris@16 702 {
Chris@16 703 typedef typename mpl::find_if<
Chris@16 704 context_type_list,
Chris@16 705 mpl::contains<
Chris@16 706 typename DestinationState::context_type_list,
Chris@16 707 mpl::placeholders::_ > >::type common_context_iter;
Chris@16 708 typedef typename mpl::deref< common_context_iter >::type
Chris@16 709 common_context_type;
Chris@16 710 typedef typename mpl::distance<
Chris@16 711 typename mpl::begin< context_type_list >::type,
Chris@16 712 common_context_iter >::type termination_state_position;
Chris@16 713 typedef typename mpl::push_front< context_type_list, MostDerived >::type
Chris@16 714 possible_transition_contexts;
Chris@16 715 typedef typename mpl::at<
Chris@16 716 possible_transition_contexts,
Chris@16 717 termination_state_position >::type termination_state_type;
Chris@16 718
Chris@16 719 termination_state_type & terminationState(
Chris@16 720 context< termination_state_type >() );
Chris@16 721 const typename
Chris@16 722 common_context_type::inner_context_ptr_type pCommonContext(
Chris@16 723 terminationState.template context_ptr< common_context_type >() );
Chris@16 724 outermost_context_base_type & outermostContextBase(
Chris@16 725 pCommonContext->outermost_context_base() );
Chris@16 726
Chris@16 727 #ifdef BOOST_STATECHART_RELAX_TRANSITION_CONTEXT
Chris@16 728 typedef typename mpl::distance<
Chris@16 729 typename mpl::begin< possible_transition_contexts >::type,
Chris@16 730 typename mpl::find<
Chris@16 731 possible_transition_contexts, TransitionContext >::type
Chris@16 732 >::type proposed_transition_context_position;
Chris@16 733
Chris@16 734 typedef typename mpl::plus<
Chris@16 735 termination_state_position,
Chris@16 736 mpl::long_< 1 >
Chris@16 737 >::type uml_transition_context_position;
Chris@16 738
Chris@16 739 typedef typename mpl::deref< typename mpl::max_element<
Chris@16 740 mpl::list<
Chris@16 741 proposed_transition_context_position,
Chris@16 742 uml_transition_context_position >,
Chris@16 743 mpl::greater< mpl::placeholders::_, mpl::placeholders::_ >
Chris@16 744 >::type >::type real_transition_context_position;
Chris@16 745
Chris@16 746 typedef typename mpl::at<
Chris@16 747 possible_transition_contexts,
Chris@16 748 real_transition_context_position >::type real_transition_context_type;
Chris@16 749
Chris@16 750 #ifdef BOOST_MSVC
Chris@16 751 # pragma warning( push )
Chris@16 752 # pragma warning( disable: 4127 ) // conditional expression is constant
Chris@16 753 #endif
Chris@16 754 if ( ( proposed_transition_context_position::value == 0 ) &&
Chris@16 755 ( inner_initial_list_size::value == 0 ) )
Chris@16 756 {
Chris@16 757 transitionAction( *polymorphic_downcast< MostDerived * >( this ) );
Chris@16 758 outermostContextBase.terminate_as_part_of_transit( terminationState );
Chris@16 759 }
Chris@16 760 else if ( proposed_transition_context_position::value >=
Chris@16 761 uml_transition_context_position::value )
Chris@16 762 {
Chris@16 763 real_transition_context_type & transitionContext =
Chris@16 764 context< real_transition_context_type >();
Chris@16 765 outermostContextBase.terminate_as_part_of_transit( terminationState );
Chris@16 766 transitionAction( transitionContext );
Chris@16 767 }
Chris@16 768 else
Chris@16 769 {
Chris@16 770 typename real_transition_context_type::inner_context_ptr_type
Chris@16 771 pTransitionContext = context_ptr< real_transition_context_type >();
Chris@16 772 outermostContextBase.terminate_as_part_of_transit(
Chris@16 773 *pTransitionContext );
Chris@16 774 transitionAction( *pTransitionContext );
Chris@16 775 pTransitionContext = 0;
Chris@16 776 outermostContextBase.terminate_as_part_of_transit( terminationState );
Chris@16 777 }
Chris@16 778 #ifdef BOOST_MSVC
Chris@16 779 # pragma warning( pop )
Chris@16 780 #endif
Chris@16 781 #else
Chris@16 782 outermostContextBase.terminate_as_part_of_transit( terminationState );
Chris@16 783 transitionAction( *pCommonContext );
Chris@16 784 #endif
Chris@16 785
Chris@16 786 typedef typename detail::make_context_list<
Chris@16 787 common_context_type, DestinationState >::type context_list_type;
Chris@16 788
Chris@16 789 // If you receive a
Chris@16 790 // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or
Chris@16 791 // similar compiler error here then you tried to make an invalid
Chris@16 792 // transition between different orthogonal regions.
Chris@16 793 BOOST_STATIC_ASSERT( ( mpl::equal_to<
Chris@16 794 typename termination_state_type::orthogonal_position,
Chris@16 795 typename mpl::front< context_list_type >::type::orthogonal_position
Chris@16 796 >::value ) );
Chris@16 797
Chris@16 798 detail::constructor<
Chris@16 799 context_list_type, outermost_context_base_type >::construct(
Chris@16 800 pCommonContext, outermostContextBase );
Chris@16 801
Chris@16 802 return detail::result_utility::make_result( detail::do_discard_event );
Chris@16 803 }
Chris@16 804
Chris@16 805 struct local_react_impl_non_empty
Chris@16 806 {
Chris@16 807 template< class ReactionList, class State >
Chris@16 808 static detail::reaction_result local_react_impl(
Chris@16 809 State & stt,
Chris@16 810 const event_base_type & evt,
Chris@16 811 typename rtti_policy_type::id_type eventType )
Chris@16 812 {
Chris@16 813 detail::reaction_result reactionResult =
Chris@16 814 mpl::front< ReactionList >::type::react(
Chris@16 815 *polymorphic_downcast< MostDerived * >( &stt ),
Chris@16 816 evt, eventType );
Chris@16 817
Chris@16 818 if ( reactionResult == detail::no_reaction )
Chris@16 819 {
Chris@16 820 reactionResult = stt.template local_react<
Chris@16 821 typename mpl::pop_front< ReactionList >::type >(
Chris@16 822 evt, eventType );
Chris@16 823 }
Chris@16 824
Chris@16 825 return reactionResult;
Chris@16 826 }
Chris@16 827 };
Chris@16 828 friend struct local_react_impl_non_empty;
Chris@16 829
Chris@16 830 struct local_react_impl_empty
Chris@16 831 {
Chris@16 832 template< class ReactionList, class State >
Chris@16 833 static detail::reaction_result local_react_impl(
Chris@16 834 State &, const event_base_type &, typename rtti_policy_type::id_type )
Chris@16 835 {
Chris@16 836 return detail::do_forward_event;
Chris@16 837 }
Chris@16 838 };
Chris@16 839
Chris@16 840 template< class ReactionList >
Chris@16 841 detail::reaction_result local_react(
Chris@16 842 const event_base_type & evt,
Chris@16 843 typename rtti_policy_type::id_type eventType )
Chris@16 844 {
Chris@16 845 typedef typename mpl::if_<
Chris@16 846 mpl::empty< ReactionList >,
Chris@16 847 local_react_impl_empty,
Chris@16 848 local_react_impl_non_empty
Chris@16 849 >::type impl;
Chris@16 850 return impl::template local_react_impl< ReactionList >(
Chris@16 851 *this, evt, eventType );
Chris@16 852 }
Chris@16 853
Chris@16 854 struct outer_state_ptr_impl_non_outermost
Chris@16 855 {
Chris@16 856 template< class State >
Chris@16 857 static const state_base_type * outer_state_ptr_impl( const State & stt )
Chris@16 858 {
Chris@16 859 return get_pointer( stt.pContext_ );
Chris@16 860 }
Chris@16 861 };
Chris@16 862 friend struct outer_state_ptr_impl_non_outermost;
Chris@16 863
Chris@16 864 struct outer_state_ptr_impl_outermost
Chris@16 865 {
Chris@16 866 template< class State >
Chris@16 867 static const state_base_type * outer_state_ptr_impl( const State & )
Chris@16 868 {
Chris@16 869 return 0;
Chris@16 870 }
Chris@16 871 };
Chris@16 872
Chris@16 873 struct deep_construct_inner_impl_non_empty
Chris@16 874 {
Chris@16 875 template< class InnerList >
Chris@16 876 static void deep_construct_inner_impl(
Chris@16 877 const inner_context_ptr_type & pInnerContext,
Chris@16 878 outermost_context_base_type & outermostContextBase )
Chris@16 879 {
Chris@16 880 typedef typename mpl::front< InnerList >::type current_inner;
Chris@16 881
Chris@16 882 // If you receive a
Chris@16 883 // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or
Chris@16 884 // similar compiler error here then there is a mismatch between the
Chris@16 885 // orthogonal position of a state and its position in the inner
Chris@16 886 // initial list of its outer state.
Chris@16 887 BOOST_STATIC_ASSERT( ( is_same<
Chris@16 888 current_inner,
Chris@16 889 typename mpl::at<
Chris@16 890 typename current_inner::context_type::inner_initial_list,
Chris@16 891 typename current_inner::orthogonal_position >::type >::value ) );
Chris@16 892
Chris@16 893 current_inner::deep_construct( pInnerContext, outermostContextBase );
Chris@16 894 deep_construct_inner< typename mpl::pop_front< InnerList >::type >(
Chris@16 895 pInnerContext, outermostContextBase );
Chris@16 896 }
Chris@16 897 };
Chris@16 898
Chris@16 899 struct deep_construct_inner_impl_empty
Chris@16 900 {
Chris@16 901 template< class InnerList >
Chris@16 902 static void deep_construct_inner_impl(
Chris@16 903 const inner_context_ptr_type &, outermost_context_base_type & ) {}
Chris@16 904 };
Chris@16 905
Chris@16 906 struct check_store_shallow_history_impl_no
Chris@16 907 {
Chris@16 908 template< class State >
Chris@16 909 static void check_store_shallow_history_impl( State & ) {}
Chris@16 910 };
Chris@16 911
Chris@16 912 struct check_store_shallow_history_impl_yes
Chris@16 913 {
Chris@16 914 template< class State >
Chris@16 915 static void check_store_shallow_history_impl( State & stt )
Chris@16 916 {
Chris@16 917 stt.outermost_context_base().template store_shallow_history<
Chris@16 918 MostDerived >();
Chris@16 919 }
Chris@16 920 };
Chris@16 921 friend struct check_store_shallow_history_impl_yes;
Chris@16 922
Chris@16 923 template< class StoreShallowHistory >
Chris@16 924 void check_store_shallow_history()
Chris@16 925 {
Chris@16 926 typedef typename mpl::if_<
Chris@16 927 StoreShallowHistory,
Chris@16 928 check_store_shallow_history_impl_yes,
Chris@16 929 check_store_shallow_history_impl_no
Chris@16 930 >::type impl;
Chris@16 931 impl::check_store_shallow_history_impl( *this );
Chris@16 932 }
Chris@16 933
Chris@16 934 struct check_store_deep_history_impl_no
Chris@16 935 {
Chris@16 936 template< class State >
Chris@16 937 static void check_store_deep_history_impl( State & ) {}
Chris@16 938 };
Chris@16 939
Chris@16 940 struct check_store_deep_history_impl_yes
Chris@16 941 {
Chris@16 942 template< class State >
Chris@16 943 static void check_store_deep_history_impl( State & stt )
Chris@16 944 {
Chris@16 945 stt.template store_deep_history_impl< MostDerived >();
Chris@16 946 }
Chris@16 947 };
Chris@16 948 friend struct check_store_deep_history_impl_yes;
Chris@16 949
Chris@16 950 template< class StoreDeepHistory >
Chris@16 951 void check_store_deep_history()
Chris@16 952 {
Chris@16 953 typedef typename mpl::if_<
Chris@16 954 StoreDeepHistory,
Chris@16 955 check_store_deep_history_impl_yes,
Chris@16 956 check_store_deep_history_impl_no
Chris@16 957 >::type impl;
Chris@16 958 impl::check_store_deep_history_impl( *this );
Chris@16 959 }
Chris@16 960
Chris@16 961
Chris@16 962 context_ptr_type pContext_;
Chris@16 963 };
Chris@16 964
Chris@16 965
Chris@16 966
Chris@16 967 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
Chris@16 968 } // namespace statechart
Chris@16 969 #endif
Chris@16 970
Chris@16 971
Chris@16 972
Chris@16 973 template< class MostDerived, class Context,
Chris@16 974 class InnerInitial, history_mode historyMode >
Chris@16 975 inline void intrusive_ptr_release( const ::boost::statechart::simple_state<
Chris@16 976 MostDerived, Context, InnerInitial, historyMode > * pBase )
Chris@16 977 {
Chris@16 978 if ( pBase->release() )
Chris@16 979 {
Chris@16 980 // The cast is necessary because the simple_state destructor is non-
Chris@16 981 // virtual (and inaccessible from this context)
Chris@16 982 delete polymorphic_downcast< const MostDerived * >( pBase );
Chris@16 983 }
Chris@16 984 }
Chris@16 985
Chris@16 986
Chris@16 987
Chris@16 988 #ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
Chris@16 989 } // namespace statechart
Chris@16 990 #endif
Chris@16 991
Chris@16 992
Chris@16 993
Chris@16 994 } // namespace boost
Chris@16 995
Chris@16 996
Chris@16 997
Chris@16 998 #endif