1 #ifndef BOOST_STATECHART_STATE_MACHINE_HPP_INCLUDED
2 #define BOOST_STATECHART_STATE_MACHINE_HPP_INCLUDED
3 //////////////////////////////////////////////////////////////////////////////
4 // Copyright 2002-2008 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 //////////////////////////////////////////////////////////////////////////////
11 #include <boost/statechart/event.hpp>
12 #include <boost/statechart/null_exception_translator.hpp>
13 #include <boost/statechart/result.hpp>
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>
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>
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>
40 #include <boost/detail/allocator_utilities.hpp>
43 # pragma warning( push )
44 # pragma warning( disable: 4702 ) // unreachable code (in release mode only)
50 # pragma warning( pop )
53 #include <memory> // std::allocator
54 #include <typeinfo> // std::bad_cast
55 #include <functional> // std::less
69 //////////////////////////////////////////////////////////////////////////////
70 template< class StateBaseType
, class EventBaseType
, class IdType
>
74 //////////////////////////////////////////////////////////////////////////
76 StateBaseType
& toState
,
77 const EventBaseType
& evt
,
80 toState_( toState
), evt_( evt
), eventType_( eventType
)
86 return detail::result_utility::make_result(
87 toState_
.react_impl( evt_
, eventType_
) );
91 //////////////////////////////////////////////////////////////////////////
92 // avoids C4512 (assignment operator could not be generated)
93 send_function
& operator=( const send_function
& );
95 StateBaseType
& toState_
;
96 const EventBaseType
& evt_
;
101 //////////////////////////////////////////////////////////////////////////////
102 struct state_cast_impl_pointer_target
105 //////////////////////////////////////////////////////////////////////////
106 template< class StateBaseType
>
107 static const StateBaseType
* deref_if_necessary(
108 const StateBaseType
* pState
)
113 template< class Target
, class IdType
>
114 static IdType
type_id()
117 return type_id_impl
< IdType
>( p
);
120 static bool found( const void * pFound
)
125 template< class Target
>
126 static Target
not_found()
132 //////////////////////////////////////////////////////////////////////////
133 template< class IdType
, class Type
>
134 static IdType
type_id_impl( const Type
* )
136 return Type::static_type();
140 struct state_cast_impl_reference_target
142 template< class StateBaseType
>
143 static const StateBaseType
& deref_if_necessary(
144 const StateBaseType
* pState
)
149 template< class Target
, class IdType
>
150 static IdType
type_id()
152 return remove_reference
< Target
>::type::static_type();
155 template< class Dummy
>
156 static bool found( const Dummy
& )
161 template< class Target
>
162 static Target
not_found()
164 throw std::bad_cast();
168 template< class Target
>
169 struct state_cast_impl
: public mpl::if_
<
170 is_pointer
< Target
>,
171 state_cast_impl_pointer_target
,
172 state_cast_impl_reference_target
176 //////////////////////////////////////////////////////////////////////////////
177 template< class RttiPolicy
>
181 //////////////////////////////////////////////////////////////////////////
182 template< class HistorizedState
>
183 static history_key
make_history_key()
186 HistorizedState::context_type::static_type(),
187 HistorizedState::orthogonal_position::value
);
190 typename
RttiPolicy::id_type
history_context_type() const
192 return historyContextType_
;
195 friend bool operator<(
196 const history_key
& left
, const history_key
& right
)
199 std::less
< typename
RttiPolicy::id_type
>()(
200 left
.historyContextType_
, right
.historyContextType_
) ||
201 ( ( left
.historyContextType_
== right
.historyContextType_
) &&
202 ( left
.historizedOrthogonalRegion_
<
203 right
.historizedOrthogonalRegion_
) );
207 //////////////////////////////////////////////////////////////////////////
209 typename
RttiPolicy::id_type historyContextType
,
210 orthogonal_position_type historizedOrthogonalRegion
212 historyContextType_( historyContextType
),
213 historizedOrthogonalRegion_( historizedOrthogonalRegion
)
217 // avoids C4512 (assignment operator could not be generated)
218 history_key
& operator=( const history_key
& );
220 const typename
RttiPolicy::id_type historyContextType_
;
221 const orthogonal_position_type historizedOrthogonalRegion_
;
226 } // namespace detail
230 //////////////////////////////////////////////////////////////////////////////
231 template< class MostDerived
,
233 class Allocator
= std::allocator
< void >,
234 class ExceptionTranslator
= null_exception_translator
>
235 class state_machine
: noncopyable
238 //////////////////////////////////////////////////////////////////////////
239 typedef Allocator allocator_type
;
240 typedef detail::rtti_policy rtti_policy_type
;
241 typedef event_base event_base_type
;
242 typedef intrusive_ptr
< const event_base_type
> event_base_ptr_type
;
249 terminator
guard( *this );
250 detail::result_utility::get_result( translator_(
251 initial_construct_function( *this ),
252 exception_event_handler( *this ) ) );
256 process_queued_events();
261 terminator
guard( *this );
262 detail::result_utility::get_result( translator_(
263 terminate_function( *this ),
264 exception_event_handler( *this ) ) );
268 bool terminated() const
270 return pOutermostState_
== 0;
273 void process_event( const event_base_type
& evt
)
276 process_queued_events();
279 template< class Target
>
280 Target
state_cast() const
282 typedef detail::state_cast_impl
< Target
> impl
;
284 for ( typename
state_list_type::const_iterator pCurrentLeafState
=
285 currentStates_
.begin();
286 pCurrentLeafState
!= currentStatesEnd_
;
287 ++pCurrentLeafState
)
289 const state_base_type
* pCurrentState(
290 get_pointer( *pCurrentLeafState
) );
292 while ( pCurrentState
!= 0 )
294 // The unnecessary try/catch overhead for pointer targets is
295 // typically small compared to the cycles dynamic_cast needs
296 #ifndef BOOST_NO_EXCEPTIONS
300 Target result
= dynamic_cast< Target
>(
301 impl::deref_if_necessary( pCurrentState
) );
303 if ( impl::found( result
) )
308 #ifndef BOOST_NO_EXCEPTIONS
309 // Intentionally swallow std::bad_cast exceptions. We'll throw one
310 // ourselves when we fail to find a state that can be cast to Target
311 catch ( const std::bad_cast
& ) {}
314 pCurrentState
= pCurrentState
->outer_state_ptr();
318 return impl::template not_found
< Target
>();
321 template< class Target
>
322 Target
state_downcast() const
324 typedef detail::state_cast_impl
< Target
> impl
;
326 typename
rtti_policy_type::id_type targetType
=
327 impl::template type_id
< Target
, rtti_policy_type::id_type
>();
329 for ( typename
state_list_type::const_iterator pCurrentLeafState
=
330 currentStates_
.begin();
331 pCurrentLeafState
!= currentStatesEnd_
;
332 ++pCurrentLeafState
)
334 const state_base_type
* pCurrentState(
335 get_pointer( *pCurrentLeafState
) );
337 while ( pCurrentState
!= 0 )
339 if ( pCurrentState
->dynamic_type() == targetType
)
341 return static_cast< Target
>(
342 impl::deref_if_necessary( pCurrentState
) );
345 pCurrentState
= pCurrentState
->outer_state_ptr();
349 return impl::template not_found
< Target
>();
352 typedef detail::state_base
< allocator_type
, rtti_policy_type
>
355 class state_iterator
: public std::iterator
<
356 std::forward_iterator_tag
,
357 state_base_type
, std::ptrdiff_t
358 #ifndef BOOST_MSVC_STD_ITERATOR
359 , const state_base_type
*, const state_base_type
&
364 //////////////////////////////////////////////////////////////////////
365 explicit state_iterator(
366 typename
state_base_type::state_list_type::const_iterator
368 ) : baseIterator_( baseIterator
) {}
370 const state_base_type
& operator*() const { return **baseIterator_
; }
371 const state_base_type
* operator->() const
373 return &**baseIterator_
;
376 state_iterator
& operator++() { ++baseIterator_
; return *this; }
377 state_iterator
operator++( int )
379 return state_iterator( baseIterator_
++ );
382 bool operator==( const state_iterator
& right
) const
384 return baseIterator_
== right
.baseIterator_
;
386 bool operator!=( const state_iterator
& right
) const
388 return !( *this == right
);
392 typename
state_base_type::state_list_type::const_iterator
396 state_iterator
state_begin() const
398 return state_iterator( currentStates_
.begin() );
401 state_iterator
state_end() const
403 return state_iterator( currentStatesEnd_
);
406 void unconsumed_event( const event_base
& ) {}
409 //////////////////////////////////////////////////////////////////////////
411 currentStatesEnd_( currentStates_
.end() ),
412 pOutermostState_( 0 ),
413 isInnermostCommonOuter_( false ),
414 performFullExit_( true )
418 // This destructor was only made virtual so that that
419 // polymorphic_downcast can be used to cast to MostDerived.
420 virtual ~state_machine()
422 terminate_impl( false );
426 //////////////////////////////////////////////////////////////////////////
427 // The following declarations should be protected.
428 // They are only public because many compilers lack template friends.
429 //////////////////////////////////////////////////////////////////////////
430 void post_event( const event_base_ptr_type
& pEvent
)
432 BOOST_ASSERT( get_pointer( pEvent
) != 0 );
433 eventQueue_
.push_back( pEvent
);
436 void post_event( const event_base
& evt
)
438 post_event( evt
.intrusive_from_this() );
442 //////////////////////////////////////////////////////////////////////////
443 // The following declarations should be private.
444 // They are only public because many compilers lack template friends.
445 //////////////////////////////////////////////////////////////////////////
446 typedef MostDerived inner_context_type
;
447 typedef mpl::integral_c
< detail::orthogonal_position_type
, 0 >
448 inner_orthogonal_position
;
449 typedef mpl::integral_c
< detail::orthogonal_position_type
, 1 >
450 no_of_orthogonal_regions
;
452 typedef MostDerived outermost_context_type
;
453 typedef state_machine outermost_context_base_type
;
454 typedef state_machine
* inner_context_ptr_type
;
455 typedef typename
state_base_type::node_state_base_ptr_type
456 node_state_base_ptr_type
;
457 typedef typename
state_base_type::leaf_state_ptr_type leaf_state_ptr_type
;
458 typedef typename
state_base_type::state_list_type state_list_type
;
460 typedef mpl::clear
< mpl::list
<> >::type context_type_list
;
462 typedef mpl::bool_
< false > shallow_history
;
463 typedef mpl::bool_
< false > deep_history
;
464 typedef mpl::bool_
< false > inherited_deep_history
;
466 detail::reaction_result
react_impl(
467 const event_base_type
&,
468 typename
rtti_policy_type::id_type
)
470 return detail::do_forward_event
;
474 inner_context_ptr_type
&,
475 typename
state_base_type::node_state_base_ptr_type
&,
478 void set_outermost_unstable_state(
479 typename
state_base_type::node_state_base_ptr_type
&
480 pOutermostUnstableState
)
482 pOutermostUnstableState
= 0;
485 // Returns a reference to the context identified by the template
486 // parameter. This can either be _this_ object or one of its direct or
487 // indirect contexts.
488 template< class Context
>
491 // As we are in the outermost context here, only this object can be
493 return *polymorphic_downcast
< MostDerived
* >( this );
496 template< class Context
>
497 const Context
& context() const
499 // As we are in the outermost context here, only this object can be
501 return *polymorphic_downcast
< const MostDerived
* >( this );
504 outermost_context_type
& outermost_context()
506 return *polymorphic_downcast
< MostDerived
* >( this );
509 const outermost_context_type
& outermost_context() const
511 return *polymorphic_downcast
< const MostDerived
* >( this );
514 outermost_context_base_type
& outermost_context_base()
519 const outermost_context_base_type
& outermost_context_base() const
524 void terminate_as_reaction( state_base_type
& theState
)
526 terminate_impl( theState
, performFullExit_
);
527 pOutermostUnstableState_
= 0;
530 void terminate_as_part_of_transit( state_base_type
& theState
)
532 terminate_impl( theState
, performFullExit_
);
533 isInnermostCommonOuter_
= true;
536 void terminate_as_part_of_transit( state_machine
& )
538 terminate_impl( *pOutermostState_
, performFullExit_
);
539 isInnermostCommonOuter_
= true;
543 template< class State
>
544 void add( const intrusive_ptr
< State
> & pState
)
546 // The second dummy argument is necessary because the call to the
547 // overloaded function add_impl would otherwise be ambiguous.
548 node_state_base_ptr_type pNewOutermostUnstableStateCandidate
=
549 add_impl( pState
, *pState
);
551 if ( isInnermostCommonOuter_
||
552 ( is_in_highest_orthogonal_region
< State
>() &&
553 ( get_pointer( pOutermostUnstableState_
) ==
554 pState
->State::outer_state_ptr() ) ) )
556 isInnermostCommonOuter_
= false;
557 pOutermostUnstableState_
= pNewOutermostUnstableStateCandidate
;
562 void add_inner_state(
563 detail::orthogonal_position_type position
,
564 state_base_type
* pOutermostState
)
566 BOOST_ASSERT( position
== 0 );
567 detail::avoid_unused_warning( position
);
568 pOutermostState_
= pOutermostState
;
571 void remove_inner_state( detail::orthogonal_position_type position
)
573 BOOST_ASSERT( position
== 0 );
574 detail::avoid_unused_warning( position
);
575 pOutermostState_
= 0;
580 const event_base_type
& evt
,
581 const state_base_type
* pForState
)
583 deferredMap_
[ pForState
].push_back( evt
.intrusive_from_this() );
586 void release_events( const state_base_type
* pForState
)
588 const typename
deferred_map_type::iterator pFound
=
589 deferredMap_
.find( pForState
);
591 // We are not guaranteed to find an entry because a state is marked for
592 // having deferred events _before_ the event is actually deferred. An
593 // exception might be thrown during deferral.
594 if ( pFound
!= deferredMap_
.end() )
596 eventQueue_
.splice( eventQueue_
.end(), pFound
->second
);
597 deferredMap_
.erase( pFound
);
602 template< class HistorizedState
>
603 void store_shallow_history()
605 // 5.2.10.6 declares that reinterpret_casting a function pointer to a
606 // different function pointer and back must yield the same value. The
607 // following reinterpret_cast is the first half of such a sequence.
610 history_key_type::make_history_key
< HistorizedState
>(),
611 reinterpret_cast< void (*)() >( &HistorizedState::deep_construct
) );
615 class HistoryContext
,
616 detail::orthogonal_position_type orthogonalPosition
>
617 void clear_shallow_history()
620 // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or
621 // similar compiler error here then you tried to clear shallow history
622 // for a state that does not have shallow history. That is, the state
623 // does not pass either statechart::has_shallow_history or
624 // statechart::has_full_history to its base class template.
625 BOOST_STATIC_ASSERT( HistoryContext::shallow_history::value
);
627 typedef typename
mpl::at_c
<
628 typename
HistoryContext::inner_initial_list
,
629 orthogonalPosition
>::type historized_state
;
633 history_key_type::make_history_key
< historized_state
>(),
637 template< class DefaultState
>
638 void construct_with_shallow_history(
639 const typename
DefaultState::context_ptr_type
& pContext
)
641 construct_with_history_impl
< DefaultState
>(
642 shallowHistoryMap_
, pContext
);
646 template< class HistorizedState
, class LeafState
>
647 void store_deep_history()
649 typedef typename
detail::make_context_list
<
650 typename
HistorizedState::context_type
,
651 LeafState
>::type history_context_list
;
652 typedef detail::constructor
<
653 history_context_list
, outermost_context_base_type
> constructor_type
;
654 // 5.2.10.6 declares that reinterpret_casting a function pointer to a
655 // different function pointer and back must yield the same value. The
656 // following reinterpret_cast is the first half of such a sequence.
659 history_key_type::make_history_key
< HistorizedState
>(),
660 reinterpret_cast< void (*)() >( &constructor_type::construct
) );
664 class HistoryContext
,
665 detail::orthogonal_position_type orthogonalPosition
>
666 void clear_deep_history()
669 // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or
670 // similar compiler error here then you tried to clear deep history for
671 // a state that does not have deep history. That is, the state does not
672 // pass either statechart::has_deep_history or
673 // statechart::has_full_history to its base class template
674 BOOST_STATIC_ASSERT( HistoryContext::deep_history::value
);
676 typedef typename
mpl::at_c
<
677 typename
HistoryContext::inner_initial_list
,
678 orthogonalPosition
>::type historized_state
;
682 history_key_type::make_history_key
< historized_state
>(),
686 template< class DefaultState
>
687 void construct_with_deep_history(
688 const typename
DefaultState::context_ptr_type
& pContext
)
690 construct_with_history_impl
< DefaultState
>(
691 deepHistoryMap_
, pContext
);
694 private: // implementation
695 //////////////////////////////////////////////////////////////////////////
696 void initial_construct()
698 InitialState::initial_deep_construct(
699 *polymorphic_downcast
< MostDerived
* >( this ) );
702 class initial_construct_function
705 //////////////////////////////////////////////////////////////////////
706 initial_construct_function( state_machine
& machine
) :
713 machine_
.initial_construct();
714 return detail::result_utility::make_result(
715 detail::do_discard_event
); // there is nothing to be consumed
719 //////////////////////////////////////////////////////////////////////
720 // avoids C4512 (assignment operator could not be generated)
721 initial_construct_function
& operator=(
722 const initial_construct_function
& );
724 state_machine
& machine_
;
726 friend class initial_construct_function
;
728 class terminate_function
731 //////////////////////////////////////////////////////////////////////
732 terminate_function( state_machine
& machine
) : machine_( machine
) {}
736 machine_
.terminate_impl( true );
737 return detail::result_utility::make_result(
738 detail::do_discard_event
); // there is nothing to be consumed
742 //////////////////////////////////////////////////////////////////////
743 // avoids C4512 (assignment operator could not be generated)
744 terminate_function
& operator=( const terminate_function
& );
746 state_machine
& machine_
;
748 friend class terminate_function
;
750 template< class ExceptionEvent
>
751 detail::reaction_result
handle_exception_event(
752 const ExceptionEvent
& exceptionEvent
,
753 state_base_type
* pCurrentState
)
757 // there is no state that could handle the exception -> bail out
761 // If we are stable, an event handler has thrown.
762 // Otherwise, either a state constructor, a transition action or an exit
763 // function has thrown and the state machine is now in an invalid state.
764 // This situation can be resolved by the exception event handler
765 // function by orderly transiting to another state or terminating.
766 // As a result of this, the machine must not be unstable when this
768 state_base_type
* const pOutermostUnstableState
=
769 get_pointer( pOutermostUnstableState_
);
770 state_base_type
* const pHandlingState
= pOutermostUnstableState
== 0 ?
771 pCurrentState
: pOutermostUnstableState
;
773 BOOST_ASSERT( pHandlingState
!= 0 );
775 // Setting a member variable to a special value for the duration of a
776 // call surely looks like a kludge (normally it should be a parameter of
777 // the call). However, in this case it is unavoidable because the call
778 // below could result in a call to user code where passing through an
779 // additional bool parameter is not acceptable.
780 performFullExit_
= false;
781 const detail::reaction_result reactionResult
= pHandlingState
->react_impl(
782 exceptionEvent
, exceptionEvent
.dynamic_type() );
783 // If the above call throws then performFullExit_ will obviously not be
784 // set back to true. In this case the termination triggered by the
785 // scope guard further up in the call stack will take care of this.
786 performFullExit_
= true;
788 if ( ( reactionResult
!= detail::do_discard_event
) ||
789 ( get_pointer( pOutermostUnstableState_
) != 0 ) )
794 return detail::do_discard_event
;
797 class exception_event_handler
800 //////////////////////////////////////////////////////////////////////
801 exception_event_handler(
802 state_machine
& machine
,
803 state_base_type
* pCurrentState
= 0
806 pCurrentState_( pCurrentState
)
810 template< class ExceptionEvent
>
812 const ExceptionEvent
& exceptionEvent
)
814 return detail::result_utility::make_result(
815 machine_
.handle_exception_event(
816 exceptionEvent
, pCurrentState_
) );
820 //////////////////////////////////////////////////////////////////////
821 // avoids C4512 (assignment operator could not be generated)
822 exception_event_handler
& operator=(
823 const exception_event_handler
& );
825 state_machine
& machine_
;
826 state_base_type
* pCurrentState_
;
828 friend class exception_event_handler
;
833 //////////////////////////////////////////////////////////////////////
834 terminator( state_machine
& machine
) :
835 machine_( machine
), dismissed_( false ) {}
838 if ( !dismissed_
) { machine_
.terminate_impl( false ); }
840 void dismiss() { dismissed_
= true; }
843 //////////////////////////////////////////////////////////////////////
844 // avoids C4512 (assignment operator could not be generated)
845 terminator
& operator=( const terminator
& );
847 state_machine
& machine_
;
850 friend class terminator
;
853 void send_event( const event_base_type
& evt
)
855 terminator
guard( *this );
856 BOOST_ASSERT( get_pointer( pOutermostUnstableState_
) == 0 );
857 const typename
rtti_policy_type::id_type eventType
= evt
.dynamic_type();
858 detail::reaction_result reactionResult
= detail::do_forward_event
;
861 typename
state_list_type::iterator pState
= currentStates_
.begin();
862 ( reactionResult
== detail::do_forward_event
) &&
863 ( pState
!= currentStatesEnd_
);
866 // CAUTION: The following statement could modify our state list!
867 // We must not continue iterating if the event was consumed
868 reactionResult
= detail::result_utility::get_result( translator_(
869 detail::send_function
<
870 state_base_type
, event_base_type
, rtti_policy_type::id_type
>(
871 **pState
, evt
, eventType
),
872 exception_event_handler( *this, get_pointer( *pState
) ) ) );
877 if ( reactionResult
== detail::do_forward_event
)
879 polymorphic_downcast
< MostDerived
* >( this )->unconsumed_event( evt
);
884 void process_queued_events()
886 while ( !eventQueue_
.empty() )
888 const event_base_ptr_type
pCurrentEvent( eventQueue_
.front() );
889 eventQueue_
.pop_front();
890 send_event( *pCurrentEvent
);
895 void terminate_impl( bool performFullExit
)
897 performFullExit_
= true;
901 // this also empties deferredMap_
902 terminate_impl( *pOutermostState_
, performFullExit
);
906 shallowHistoryMap_
.clear();
907 deepHistoryMap_
.clear();
910 void terminate_impl( state_base_type
& theState
, bool performFullExit
)
912 isInnermostCommonOuter_
= false;
914 // If pOutermostUnstableState_ == 0, we know for sure that
915 // currentStates_.size() > 0, otherwise theState couldn't be alive any
917 if ( get_pointer( pOutermostUnstableState_
) != 0 )
919 theState
.remove_from_state_list(
920 currentStatesEnd_
, pOutermostUnstableState_
, performFullExit
);
922 // Optimization: We want to find out whether currentStates_ has size 1
923 // and if yes use the optimized implementation below. Since
924 // list<>::size() is implemented quite inefficiently in some std libs
925 // it is best to just decrement the currentStatesEnd_ here and
926 // increment it again, if the test failed.
927 else if ( currentStates_
.begin() == --currentStatesEnd_
)
929 // The machine is stable and there is exactly one innermost state.
930 // The following optimization is only correct for a stable machine
931 // without orthogonal regions.
932 leaf_state_ptr_type
& pState
= *currentStatesEnd_
;
934 pState
, pOutermostUnstableState_
, performFullExit
);
938 BOOST_ASSERT( currentStates_
.size() > 1 );
939 // The machine is stable and there are multiple innermost states
940 theState
.remove_from_state_list(
941 ++currentStatesEnd_
, pOutermostUnstableState_
, performFullExit
);
946 node_state_base_ptr_type
add_impl(
947 const leaf_state_ptr_type
& pState
,
948 detail::leaf_state
< allocator_type
, rtti_policy_type
> & )
950 if ( currentStatesEnd_
== currentStates_
.end() )
952 pState
->set_list_position(
953 currentStates_
.insert( currentStatesEnd_
, pState
) );
957 *currentStatesEnd_
= pState
;
958 pState
->set_list_position( currentStatesEnd_
);
965 node_state_base_ptr_type
add_impl(
966 const node_state_base_ptr_type
& pState
,
972 template< class State
>
973 static bool is_in_highest_orthogonal_region()
975 return mpl::equal_to
<
976 typename
State::orthogonal_position
,
978 typename
State::context_type::no_of_orthogonal_regions
,
979 mpl::integral_c
< detail::orthogonal_position_type
, 1 > >
984 typedef detail::history_key
< rtti_policy_type
> history_key_type
;
987 history_key_type
, void (*)(),
988 std::less
< history_key_type
>,
989 typename
boost::detail::allocator::rebind_to
<
990 allocator_type
, std::pair
< const history_key_type
, void (*)() >
994 void store_history_impl(
995 history_map_type
& historyMap
,
996 const history_key_type
& historyId
,
997 void (*pConstructFunction
)() )
999 historyMap
[ historyId
] = pConstructFunction
;
1002 template< class DefaultState
>
1003 void construct_with_history_impl(
1004 history_map_type
& historyMap
,
1005 const typename
DefaultState::context_ptr_type
& pContext
)
1007 typename
history_map_type::iterator pFoundSlot
= historyMap
.find(
1008 history_key_type::make_history_key
< DefaultState
>() );
1010 if ( ( pFoundSlot
== historyMap
.end() ) || ( pFoundSlot
->second
== 0 ) )
1012 // We have never entered this state before or history was cleared
1013 DefaultState::deep_construct(
1014 pContext
, *polymorphic_downcast
< MostDerived
* >( this ) );
1018 typedef void construct_function(
1019 const typename
DefaultState::context_ptr_type
&,
1020 typename
DefaultState::outermost_context_base_type
& );
1021 // 5.2.10.6 declares that reinterpret_casting a function pointer to a
1022 // different function pointer and back must yield the same value. The
1023 // following reinterpret_cast is the second half of such a sequence.
1024 construct_function
* const pConstructFunction
=
1025 reinterpret_cast< construct_function
* >( pFoundSlot
->second
);
1026 (*pConstructFunction
)(
1027 pContext
, *polymorphic_downcast
< MostDerived
* >( this ) );
1032 event_base_ptr_type
,
1033 typename
boost::detail::allocator::rebind_to
<
1034 allocator_type
, event_base_ptr_type
>::type
1038 const state_base_type
*, event_queue_type
,
1039 std::less
< const state_base_type
* >,
1040 typename
boost::detail::allocator::rebind_to
<
1042 std::pair
< const state_base_type
* const, event_queue_type
>
1044 > deferred_map_type
;
1047 event_queue_type eventQueue_
;
1048 deferred_map_type deferredMap_
;
1049 state_list_type currentStates_
;
1050 typename
state_list_type::iterator currentStatesEnd_
;
1051 state_base_type
* pOutermostState_
;
1052 bool isInnermostCommonOuter_
;
1053 node_state_base_ptr_type pOutermostUnstableState_
;
1054 ExceptionTranslator translator_
;
1055 bool performFullExit_
;
1056 history_map_type shallowHistoryMap_
;
1057 history_map_type deepHistoryMap_
;
1062 } // namespace statechart
1063 } // namespace boost