Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:52:32

0001 #ifndef BOOST_STATECHART_STATE_MACHINE_HPP_INCLUDED
0002 #define BOOST_STATECHART_STATE_MACHINE_HPP_INCLUDED
0003 //////////////////////////////////////////////////////////////////////////////
0004 // Copyright 2002-2010 Andreas Huber Doenni
0005 // Distributed under the Boost Software License, Version 1.0. (See accompany-
0006 // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 //////////////////////////////////////////////////////////////////////////////
0008 
0009 
0010 
0011 #include <boost/statechart/event.hpp>
0012 #include <boost/statechart/null_exception_translator.hpp>
0013 #include <boost/statechart/result.hpp>
0014 
0015 #include <boost/statechart/detail/rtti_policy.hpp>
0016 #include <boost/statechart/detail/state_base.hpp>
0017 #include <boost/statechart/detail/leaf_state.hpp>
0018 #include <boost/statechart/detail/node_state.hpp>
0019 #include <boost/statechart/detail/constructor.hpp>
0020 #include <boost/statechart/detail/avoid_unused_warning.hpp>
0021 
0022 #include <boost/mpl/list.hpp>
0023 #include <boost/mpl/clear.hpp>
0024 #include <boost/mpl/if.hpp>
0025 #include <boost/mpl/at.hpp>
0026 #include <boost/mpl/integral_c.hpp>
0027 #include <boost/mpl/minus.hpp>
0028 #include <boost/mpl/equal_to.hpp>
0029 
0030 #include <boost/intrusive_ptr.hpp>
0031 #include <boost/type_traits/is_pointer.hpp>
0032 #include <boost/type_traits/remove_reference.hpp>
0033 #include <boost/noncopyable.hpp>
0034 #include <boost/assert.hpp>
0035 #include <boost/static_assert.hpp>
0036 #include <boost/polymorphic_cast.hpp> // boost::polymorphic_downcast
0037 // BOOST_NO_EXCEPTIONS, BOOST_MSVC, BOOST_MSVC_STD_ITERATOR
0038 #include <boost/config.hpp>
0039 
0040 #include <boost/detail/allocator_utilities.hpp>
0041 
0042 #ifdef BOOST_MSVC
0043 #  pragma warning( push )
0044 #  pragma warning( disable: 4702 ) // unreachable code (in release mode only)
0045 #endif
0046 
0047 #include <map>
0048 
0049 #ifdef BOOST_MSVC
0050 #  pragma warning( pop )
0051 #endif
0052 
0053 #include <memory>   // std::allocator
0054 #include <typeinfo> // std::bad_cast
0055 #include <functional> // std::less
0056 #include <iterator>
0057 
0058 
0059 
0060 namespace boost
0061 {
0062 namespace statechart
0063 {
0064 namespace detail
0065 {
0066 
0067 
0068 
0069 //////////////////////////////////////////////////////////////////////////////
0070 template< class StateBaseType, class EventBaseType, class IdType >
0071 class send_function
0072 {
0073   public:
0074     //////////////////////////////////////////////////////////////////////////
0075     send_function(
0076       StateBaseType & toState,
0077       const EventBaseType & evt,
0078       IdType eventType
0079     ) :
0080       toState_( toState ), evt_( evt ), eventType_( eventType )
0081     {
0082     }
0083 
0084     result operator()()
0085     {
0086       return detail::result_utility::make_result(
0087         toState_.react_impl( evt_, eventType_ ) );
0088     }
0089 
0090   private:
0091     //////////////////////////////////////////////////////////////////////////
0092     // avoids C4512 (assignment operator could not be generated)
0093     send_function & operator=( const send_function & );
0094 
0095     StateBaseType & toState_;
0096     const EventBaseType & evt_;
0097     IdType eventType_;
0098 };
0099 
0100 
0101 //////////////////////////////////////////////////////////////////////////////
0102 struct state_cast_impl_pointer_target
0103 {
0104   public:
0105     //////////////////////////////////////////////////////////////////////////
0106     template< class StateBaseType >
0107     static const StateBaseType * deref_if_necessary(
0108       const StateBaseType * pState )
0109     {
0110       return pState;
0111     }
0112 
0113     template< class Target, class IdType >
0114     static IdType type_id()
0115     {
0116       Target p = 0;
0117       return type_id_impl< IdType >( p );
0118     }
0119 
0120     static bool found( const void * pFound )
0121     {
0122       return pFound != 0;
0123     }
0124 
0125     template< class Target >
0126     static Target not_found()
0127     {
0128       return 0;
0129     }
0130 
0131   private:
0132     //////////////////////////////////////////////////////////////////////////
0133     template< class IdType, class Type >
0134     static IdType type_id_impl( const Type * )
0135     {
0136       return Type::static_type();
0137     }
0138 };
0139 
0140 struct state_cast_impl_reference_target
0141 {
0142   template< class StateBaseType >
0143   static const StateBaseType & deref_if_necessary(
0144     const StateBaseType * pState )
0145   {
0146     return *pState;
0147   }
0148 
0149   template< class Target, class IdType >
0150   static IdType type_id()
0151   {
0152     return remove_reference< Target >::type::static_type();
0153   }
0154 
0155   template< class Dummy >
0156   static bool found( const Dummy & )
0157   {
0158     return true;
0159   }
0160 
0161   template< class Target >
0162   static Target not_found()
0163   {
0164     throw std::bad_cast();
0165   }
0166 };
0167 
0168 template< class Target >
0169 struct state_cast_impl : public mpl::if_<
0170   is_pointer< Target >,
0171   state_cast_impl_pointer_target,
0172   state_cast_impl_reference_target
0173 >::type {};
0174 
0175 
0176 //////////////////////////////////////////////////////////////////////////////
0177 template< class RttiPolicy >
0178 class history_key
0179 {
0180   public:
0181     //////////////////////////////////////////////////////////////////////////
0182     template< class HistorizedState >
0183     static history_key make_history_key()
0184     {
0185       return history_key(
0186         HistorizedState::context_type::static_type(),
0187         HistorizedState::orthogonal_position::value );
0188     }
0189 
0190     typename RttiPolicy::id_type history_context_type() const
0191     {
0192       return historyContextType_;
0193     }
0194 
0195     friend bool operator<(
0196       const history_key & left, const history_key & right )
0197     {
0198       return
0199         std::less< typename RttiPolicy::id_type >()( 
0200           left.historyContextType_, right.historyContextType_ ) ||
0201         ( ( left.historyContextType_ == right.historyContextType_ ) &&
0202           ( left.historizedOrthogonalRegion_ <
0203             right.historizedOrthogonalRegion_ ) );
0204     }
0205 
0206   private:
0207     //////////////////////////////////////////////////////////////////////////
0208     history_key(
0209       typename RttiPolicy::id_type historyContextType, 
0210       orthogonal_position_type historizedOrthogonalRegion
0211     ) :
0212       historyContextType_( historyContextType ),
0213       historizedOrthogonalRegion_( historizedOrthogonalRegion )
0214     {
0215     }
0216 
0217     // avoids C4512 (assignment operator could not be generated)
0218     history_key & operator=( const history_key & );
0219 
0220     const typename RttiPolicy::id_type historyContextType_;
0221     const orthogonal_position_type historizedOrthogonalRegion_;
0222 };
0223 
0224 
0225 
0226 } // namespace detail
0227 
0228 
0229 
0230 //////////////////////////////////////////////////////////////////////////////
0231 template< class MostDerived,
0232           class InitialState,
0233           class Allocator = std::allocator< none >,
0234           class ExceptionTranslator = null_exception_translator >
0235 class state_machine : noncopyable
0236 {
0237   public:
0238     //////////////////////////////////////////////////////////////////////////
0239     typedef Allocator allocator_type;
0240     typedef detail::rtti_policy rtti_policy_type;
0241     typedef event_base event_base_type;
0242     typedef intrusive_ptr< const event_base_type > event_base_ptr_type;
0243 
0244     void initiate()
0245     {
0246       terminate();
0247 
0248       {
0249         terminator guard( *this, 0 );
0250         detail::result_utility::get_result( translator_(
0251           initial_construct_function( *this ),
0252           exception_event_handler( *this ) ) );
0253         guard.dismiss();
0254       }
0255 
0256       process_queued_events();
0257     }
0258 
0259     void terminate()
0260     {
0261       terminator guard( *this, 0 );
0262       detail::result_utility::get_result( translator_(
0263         terminate_function( *this ),
0264         exception_event_handler( *this ) ) );
0265       guard.dismiss();
0266     }
0267 
0268     bool terminated() const
0269     {
0270       return pOutermostState_ == 0;
0271     }
0272 
0273     void process_event( const event_base_type & evt )
0274     {
0275       if ( send_event( evt ) == detail::do_defer_event )
0276       {
0277         deferredEventQueue_.push_back( evt.intrusive_from_this() );
0278       }
0279 
0280       process_queued_events();
0281     }
0282 
0283     template< class Target >
0284     Target state_cast() const
0285     {
0286       typedef detail::state_cast_impl< Target > impl;
0287 
0288       for ( typename state_list_type::const_iterator pCurrentLeafState =
0289               currentStates_.begin();
0290             pCurrentLeafState != currentStatesEnd_;
0291             ++pCurrentLeafState )
0292       {
0293         const state_base_type * pCurrentState(
0294           get_pointer( *pCurrentLeafState ) );
0295 
0296         while ( pCurrentState != 0 )
0297         {
0298           // The unnecessary try/catch overhead for pointer targets is
0299           // typically small compared to the cycles dynamic_cast needs
0300           #ifndef BOOST_NO_EXCEPTIONS
0301           try
0302           #endif
0303           {
0304             Target result = dynamic_cast< Target >(
0305               impl::deref_if_necessary( pCurrentState ) );
0306 
0307             if ( impl::found( result ) )
0308             {
0309               return result;
0310             }
0311           }
0312           #ifndef BOOST_NO_EXCEPTIONS
0313           // Intentionally swallow std::bad_cast exceptions. We'll throw one
0314           // ourselves when we fail to find a state that can be cast to Target
0315           catch ( const std::bad_cast & ) {}
0316           #endif
0317 
0318           pCurrentState = pCurrentState->outer_state_ptr();
0319         }
0320       }
0321 
0322       return impl::template not_found< Target >();
0323     }
0324 
0325     template< class Target >
0326     Target state_downcast() const
0327     {
0328       typedef detail::state_cast_impl< Target > impl;
0329 
0330       typename rtti_policy_type::id_type targetType =
0331         impl::template type_id< Target, rtti_policy_type::id_type >();
0332 
0333       for ( typename state_list_type::const_iterator pCurrentLeafState =
0334               currentStates_.begin();
0335             pCurrentLeafState != currentStatesEnd_;
0336             ++pCurrentLeafState )
0337       {
0338         const state_base_type * pCurrentState(
0339           get_pointer( *pCurrentLeafState ) );
0340 
0341         while ( pCurrentState != 0 )
0342         {
0343           if ( pCurrentState->dynamic_type() == targetType )
0344           {
0345             return static_cast< Target >(
0346               impl::deref_if_necessary( pCurrentState ) );
0347           }
0348 
0349           pCurrentState = pCurrentState->outer_state_ptr();
0350         }
0351       }
0352 
0353       return impl::template not_found< Target >();
0354     }
0355 
0356     typedef detail::state_base< allocator_type, rtti_policy_type >
0357       state_base_type;
0358 
0359     class state_iterator : public std::iterator<
0360       std::forward_iterator_tag,
0361       state_base_type, std::ptrdiff_t
0362       #ifndef BOOST_MSVC_STD_ITERATOR
0363       , const state_base_type *, const state_base_type &
0364       #endif
0365     >
0366     {
0367       public:
0368         //////////////////////////////////////////////////////////////////////
0369         explicit state_iterator(
0370           typename state_base_type::state_list_type::const_iterator 
0371             baseIterator
0372         ) : baseIterator_( baseIterator ) {}
0373 
0374         const state_base_type & operator*() const { return **baseIterator_; }
0375         const state_base_type * operator->() const
0376         {
0377           return &**baseIterator_;
0378         }
0379 
0380         state_iterator & operator++() { ++baseIterator_; return *this; }
0381         state_iterator operator++( int )
0382         {
0383           return state_iterator( baseIterator_++ );
0384         }
0385 
0386         bool operator==( const state_iterator & right ) const
0387         {
0388           return baseIterator_ == right.baseIterator_;
0389         }
0390         bool operator!=( const state_iterator & right ) const
0391         {
0392           return !( *this == right );
0393         }
0394 
0395       private:
0396         typename state_base_type::state_list_type::const_iterator
0397           baseIterator_;
0398     };
0399 
0400     state_iterator state_begin() const
0401     {
0402       return state_iterator( currentStates_.begin() );
0403     }
0404 
0405     state_iterator state_end() const
0406     {
0407       return state_iterator( currentStatesEnd_ );
0408     }
0409 
0410     void unconsumed_event( const event_base & ) {}
0411 
0412   protected:
0413     //////////////////////////////////////////////////////////////////////////
0414     state_machine() :
0415       currentStatesEnd_( currentStates_.end() ),
0416       pOutermostState_( 0 ),
0417       isInnermostCommonOuter_( false ),
0418       performFullExit_( true ),
0419       pTriggeringEvent_( 0 )
0420     {
0421     }
0422 
0423     // This destructor was only made virtual so that that
0424     // polymorphic_downcast can be used to cast to MostDerived.
0425     virtual ~state_machine()
0426     {
0427       terminate_impl( false );
0428     }
0429 
0430     void post_event( const event_base_ptr_type & pEvent )
0431     {
0432       post_event_impl( pEvent );
0433     }
0434 
0435     void post_event( const event_base & evt )
0436     {
0437       post_event_impl( evt );
0438     }
0439 
0440   public:
0441     //////////////////////////////////////////////////////////////////////////
0442     // The following declarations should be protected.
0443     // They are only public because many compilers lack template friends.
0444     //////////////////////////////////////////////////////////////////////////
0445     template<
0446       class HistoryContext,
0447       detail::orthogonal_position_type orthogonalPosition >
0448     void clear_shallow_history()
0449     {
0450       // If you receive a
0451       // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or
0452       // similar compiler error here then you tried to clear shallow history
0453       // for a state that does not have shallow history. That is, the state
0454       // does not pass either statechart::has_shallow_history or
0455       // statechart::has_full_history to its base class template.
0456       BOOST_STATIC_ASSERT( HistoryContext::shallow_history::value );
0457 
0458       typedef typename mpl::at_c<
0459         typename HistoryContext::inner_initial_list,
0460         orthogonalPosition >::type historized_state;
0461 
0462       store_history_impl(
0463         shallowHistoryMap_,
0464         history_key_type::make_history_key< historized_state >(),
0465         0 );
0466     }
0467 
0468     template<
0469       class HistoryContext,
0470       detail::orthogonal_position_type orthogonalPosition >
0471     void clear_deep_history()
0472     {
0473       // If you receive a
0474       // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or
0475       // similar compiler error here then you tried to clear deep history for
0476       // a state that does not have deep history. That is, the state does not
0477       // pass either statechart::has_deep_history or
0478       // statechart::has_full_history to its base class template
0479       BOOST_STATIC_ASSERT( HistoryContext::deep_history::value );
0480 
0481       typedef typename mpl::at_c<
0482         typename HistoryContext::inner_initial_list,
0483         orthogonalPosition >::type historized_state;
0484 
0485       store_history_impl(
0486         deepHistoryMap_,
0487         history_key_type::make_history_key< historized_state >(),
0488         0 );
0489     }
0490 
0491     const event_base_type * triggering_event() const
0492     {
0493         return pTriggeringEvent_;
0494     }
0495 
0496   public:
0497     //////////////////////////////////////////////////////////////////////////
0498     // The following declarations should be private.
0499     // They are only public because many compilers lack template friends.
0500     //////////////////////////////////////////////////////////////////////////
0501     typedef MostDerived inner_context_type;
0502     typedef mpl::integral_c< detail::orthogonal_position_type, 0 >
0503       inner_orthogonal_position;
0504     typedef mpl::integral_c< detail::orthogonal_position_type, 1 >
0505       no_of_orthogonal_regions;
0506 
0507     typedef MostDerived outermost_context_type;
0508     typedef state_machine outermost_context_base_type;
0509     typedef state_machine * inner_context_ptr_type;
0510     typedef typename state_base_type::node_state_base_ptr_type
0511       node_state_base_ptr_type;
0512     typedef typename state_base_type::leaf_state_ptr_type leaf_state_ptr_type;
0513     typedef typename state_base_type::state_list_type state_list_type;
0514 
0515     typedef mpl::clear< mpl::list<> >::type context_type_list;
0516 
0517     typedef mpl::bool_< false > shallow_history;
0518     typedef mpl::bool_< false > deep_history;
0519     typedef mpl::bool_< false > inherited_deep_history;
0520 
0521     void post_event_impl( const event_base_ptr_type & pEvent )
0522     {
0523       BOOST_ASSERT( get_pointer( pEvent ) != 0 );
0524       eventQueue_.push_back( pEvent );
0525     }
0526 
0527     void post_event_impl( const event_base & evt )
0528     {
0529       post_event_impl( evt.intrusive_from_this() );
0530     }
0531 
0532     detail::reaction_result react_impl(
0533       const event_base_type &,
0534       typename rtti_policy_type::id_type )
0535     {
0536       return detail::do_forward_event;
0537     }
0538 
0539     void exit_impl(
0540       inner_context_ptr_type &,
0541       typename state_base_type::node_state_base_ptr_type &,
0542       bool ) {}
0543 
0544     void set_outermost_unstable_state(
0545       typename state_base_type::node_state_base_ptr_type &
0546         pOutermostUnstableState )
0547     {
0548       pOutermostUnstableState = 0;
0549     }
0550 
0551     // Returns a reference to the context identified by the template
0552     // parameter. This can either be _this_ object or one of its direct or
0553     // indirect contexts.
0554     template< class Context >
0555     Context & context()
0556     {
0557       // As we are in the outermost context here, only this object can be
0558       // returned.
0559       return *polymorphic_downcast< MostDerived * >( this );
0560     }
0561 
0562     template< class Context >
0563     const Context & context() const
0564     {
0565       // As we are in the outermost context here, only this object can be
0566       // returned.
0567       return *polymorphic_downcast< const MostDerived * >( this );
0568     }
0569 
0570     outermost_context_type & outermost_context()
0571     {
0572       return *polymorphic_downcast< MostDerived * >( this );
0573     }
0574 
0575     const outermost_context_type & outermost_context() const
0576     {
0577       return *polymorphic_downcast< const MostDerived * >( this );
0578     }
0579 
0580     outermost_context_base_type & outermost_context_base()
0581     {
0582       return *this;
0583     }
0584 
0585     const outermost_context_base_type & outermost_context_base() const
0586     {
0587       return *this;
0588     }
0589 
0590     void terminate_as_reaction( state_base_type & theState )
0591     {
0592       terminate_impl( theState, performFullExit_ );
0593       pOutermostUnstableState_ = 0;
0594     }
0595 
0596     void terminate_as_part_of_transit( state_base_type & theState )
0597     {
0598       terminate_impl( theState, performFullExit_ );
0599       isInnermostCommonOuter_ = true;
0600     }
0601 
0602     void terminate_as_part_of_transit( state_machine & )
0603     {
0604       terminate_impl( *pOutermostState_, performFullExit_ );
0605       isInnermostCommonOuter_ = true;
0606     }
0607 
0608 
0609     template< class State >
0610     void add( const intrusive_ptr< State > & pState )
0611     {
0612       // The second dummy argument is necessary because the call to the
0613       // overloaded function add_impl would otherwise be ambiguous.
0614       node_state_base_ptr_type pNewOutermostUnstableStateCandidate =
0615         add_impl( pState, *pState );
0616 
0617       if ( isInnermostCommonOuter_ ||
0618         ( is_in_highest_orthogonal_region< State >() &&
0619         ( get_pointer( pOutermostUnstableState_ ) ==
0620           pState->State::outer_state_ptr() ) ) )
0621       {
0622         isInnermostCommonOuter_ = false;
0623         pOutermostUnstableState_ = pNewOutermostUnstableStateCandidate;
0624       }
0625     }
0626 
0627 
0628     void add_inner_state(
0629       detail::orthogonal_position_type position,
0630       state_base_type * pOutermostState )
0631     {
0632       BOOST_ASSERT( position == 0 );
0633       detail::avoid_unused_warning( position );
0634       pOutermostState_ = pOutermostState;
0635     }
0636 
0637     void remove_inner_state( detail::orthogonal_position_type position )
0638     {
0639       BOOST_ASSERT( position == 0 );
0640       detail::avoid_unused_warning( position );
0641       pOutermostState_ = 0;
0642     }
0643 
0644 
0645     void release_events()
0646     {
0647       eventQueue_.splice( eventQueue_.begin(), deferredEventQueue_ );
0648     }
0649 
0650 
0651     template< class HistorizedState >
0652     void store_shallow_history()
0653     {
0654       // 5.2.10.6 declares that reinterpret_casting a function pointer to a
0655       // different function pointer and back must yield the same value. The
0656       // following reinterpret_cast is the first half of such a sequence.
0657       store_history_impl(
0658         shallowHistoryMap_,
0659         history_key_type::make_history_key< HistorizedState >(),
0660         reinterpret_cast< void (*)() >( &HistorizedState::deep_construct ) );
0661     }
0662 
0663     template< class DefaultState >
0664     void construct_with_shallow_history(
0665       const typename DefaultState::context_ptr_type & pContext )
0666     {
0667       construct_with_history_impl< DefaultState >(
0668         shallowHistoryMap_, pContext );
0669     }
0670 
0671 
0672     template< class HistorizedState, class LeafState >
0673     void store_deep_history()
0674     {
0675       typedef typename detail::make_context_list<
0676         typename HistorizedState::context_type,
0677         LeafState >::type history_context_list;
0678       typedef detail::constructor< 
0679         history_context_list, outermost_context_base_type > constructor_type;
0680       // 5.2.10.6 declares that reinterpret_casting a function pointer to a
0681       // different function pointer and back must yield the same value. The
0682       // following reinterpret_cast is the first half of such a sequence.
0683       store_history_impl(
0684         deepHistoryMap_, 
0685         history_key_type::make_history_key< HistorizedState >(),
0686         reinterpret_cast< void (*)() >( &constructor_type::construct ) );
0687     }
0688 
0689     template< class DefaultState >
0690     void construct_with_deep_history(
0691       const typename DefaultState::context_ptr_type & pContext )
0692     {
0693       construct_with_history_impl< DefaultState >(
0694         deepHistoryMap_, pContext );
0695     }
0696 
0697   private: // implementation
0698     //////////////////////////////////////////////////////////////////////////
0699     void initial_construct()
0700     {
0701       InitialState::initial_deep_construct(
0702         *polymorphic_downcast< MostDerived * >( this ) );
0703     }
0704 
0705     class initial_construct_function
0706     {
0707       public:
0708         //////////////////////////////////////////////////////////////////////
0709         initial_construct_function( state_machine & machine ) :
0710           machine_( machine )
0711         {
0712         }
0713 
0714         result operator()()
0715         {
0716           machine_.initial_construct();
0717           return detail::result_utility::make_result(
0718             detail::do_discard_event ); // there is nothing to be consumed
0719         }
0720 
0721       private:
0722         //////////////////////////////////////////////////////////////////////
0723         // avoids C4512 (assignment operator could not be generated)
0724         initial_construct_function & operator=(
0725           const initial_construct_function & );
0726 
0727         state_machine & machine_;
0728     };
0729     friend class initial_construct_function;
0730 
0731     class terminate_function
0732     {
0733       public:
0734         //////////////////////////////////////////////////////////////////////
0735         terminate_function( state_machine & machine ) : machine_( machine ) {}
0736 
0737         result operator()()
0738         {
0739           machine_.terminate_impl( true );
0740           return detail::result_utility::make_result(
0741             detail::do_discard_event ); // there is nothing to be consumed
0742         }
0743 
0744       private:
0745         //////////////////////////////////////////////////////////////////////
0746         // avoids C4512 (assignment operator could not be generated)
0747         terminate_function & operator=( const terminate_function & );
0748 
0749         state_machine & machine_;
0750     };
0751     friend class terminate_function;
0752 
0753     template< class ExceptionEvent >
0754     detail::reaction_result handle_exception_event(
0755       const ExceptionEvent & exceptionEvent,
0756       state_base_type * pCurrentState )
0757     {
0758       if ( terminated() )
0759       {
0760         // there is no state that could handle the exception -> bail out
0761         throw;
0762       }
0763 
0764       // If we are stable, an event handler has thrown.
0765       // Otherwise, either a state constructor, a transition action or an exit
0766       // function has thrown and the state machine is now in an invalid state.
0767       // This situation can be resolved by the exception event handler
0768       // function by orderly transiting to another state or terminating.
0769       // As a result of this, the machine must not be unstable when this
0770       // function is left.
0771       state_base_type * const pOutermostUnstableState =
0772         get_pointer( pOutermostUnstableState_ );
0773       state_base_type * const pHandlingState = pOutermostUnstableState == 0 ?
0774         pCurrentState : pOutermostUnstableState;
0775 
0776       BOOST_ASSERT( pHandlingState != 0 );
0777       terminator guard( *this, &exceptionEvent );
0778       // There is another scope guard up the call stack, which will terminate
0779       // the machine. So this guard only sets the triggering event.
0780       guard.dismiss();
0781 
0782       // Setting a member variable to a special value for the duration of a
0783       // call surely looks like a kludge (normally it should be a parameter of
0784       // the call). However, in this case it is unavoidable because the call
0785       // below could result in a call to user code where passing through an
0786       // additional bool parameter is not acceptable.
0787       performFullExit_ = false;
0788       const detail::reaction_result reactionResult = pHandlingState->react_impl(
0789         exceptionEvent, exceptionEvent.dynamic_type() );
0790       // If the above call throws then performFullExit_ will obviously not be
0791       // set back to true. In this case the termination triggered by the
0792       // scope guard further up in the call stack will take care of this.
0793       performFullExit_ = true;
0794 
0795       if ( ( reactionResult != detail::do_discard_event ) ||
0796         ( get_pointer( pOutermostUnstableState_ ) != 0 ) )
0797       {
0798         throw;
0799       }
0800 
0801       return detail::do_discard_event;
0802     }
0803 
0804     class exception_event_handler
0805     {
0806       public:
0807         //////////////////////////////////////////////////////////////////////
0808         exception_event_handler(
0809           state_machine & machine,
0810           state_base_type * pCurrentState = 0
0811         ) :
0812           machine_( machine ),
0813           pCurrentState_( pCurrentState )
0814         {
0815         }
0816 
0817         template< class ExceptionEvent >
0818         result operator()(
0819           const ExceptionEvent & exceptionEvent )
0820         {
0821           return detail::result_utility::make_result(
0822             machine_.handle_exception_event(
0823               exceptionEvent, pCurrentState_ ) );
0824         }
0825 
0826       private:
0827         //////////////////////////////////////////////////////////////////////
0828         // avoids C4512 (assignment operator could not be generated)
0829         exception_event_handler & operator=(
0830           const exception_event_handler & );
0831 
0832         state_machine & machine_;
0833         state_base_type * pCurrentState_;
0834     };
0835     friend class exception_event_handler;
0836 
0837     class terminator
0838     {
0839       public:
0840         //////////////////////////////////////////////////////////////////////
0841         terminator(
0842           state_machine & machine, const event_base * pNewTriggeringEvent ) :
0843           machine_( machine ),
0844           pOldTriggeringEvent_(machine_.pTriggeringEvent_),
0845           dismissed_( false )
0846         {
0847             machine_.pTriggeringEvent_ = pNewTriggeringEvent;
0848         }
0849 
0850         ~terminator()
0851         {
0852           if ( !dismissed_ ) { machine_.terminate_impl( false ); }
0853           machine_.pTriggeringEvent_ = pOldTriggeringEvent_;
0854         }
0855 
0856         void dismiss() { dismissed_ = true; }
0857 
0858       private:
0859         //////////////////////////////////////////////////////////////////////
0860         // avoids C4512 (assignment operator could not be generated)
0861         terminator & operator=( const terminator & );
0862 
0863         state_machine & machine_;
0864         const event_base_type * const pOldTriggeringEvent_;
0865         bool dismissed_;
0866     };
0867     friend class terminator;
0868 
0869 
0870     detail::reaction_result send_event( const event_base_type & evt )
0871     {
0872       terminator guard( *this, &evt );
0873       BOOST_ASSERT( get_pointer( pOutermostUnstableState_ ) == 0 );
0874       const typename rtti_policy_type::id_type eventType = evt.dynamic_type();
0875       detail::reaction_result reactionResult = detail::do_forward_event;
0876       
0877       for (
0878         typename state_list_type::iterator pState = currentStates_.begin();
0879         ( reactionResult == detail::do_forward_event ) &&
0880           ( pState != currentStatesEnd_ );
0881         ++pState )
0882       {
0883         // CAUTION: The following statement could modify our state list!
0884         // We must not continue iterating if the event was consumed
0885         reactionResult = detail::result_utility::get_result( translator_(
0886           detail::send_function<
0887             state_base_type, event_base_type, rtti_policy_type::id_type >(
0888               **pState, evt, eventType ),
0889           exception_event_handler( *this, get_pointer( *pState ) ) ) );
0890       }
0891 
0892       guard.dismiss();
0893 
0894       if ( reactionResult == detail::do_forward_event )
0895       {
0896         polymorphic_downcast< MostDerived * >( this )->unconsumed_event( evt );
0897       }
0898 
0899       return reactionResult;
0900     }
0901 
0902 
0903     void process_queued_events()
0904     {
0905       while ( !eventQueue_.empty() )
0906       {
0907         event_base_ptr_type pEvent = eventQueue_.front();
0908         eventQueue_.pop_front();
0909 
0910         if ( send_event( *pEvent ) == detail::do_defer_event )
0911         {
0912           deferredEventQueue_.push_back( pEvent );
0913         }
0914       }
0915     }
0916 
0917 
0918     void terminate_impl( bool performFullExit )
0919     {
0920       performFullExit_ = true;
0921 
0922       if ( !terminated() )
0923       {
0924         terminate_impl( *pOutermostState_, performFullExit );
0925       }
0926 
0927       eventQueue_.clear();
0928       deferredEventQueue_.clear();
0929       shallowHistoryMap_.clear();
0930       deepHistoryMap_.clear();
0931     }
0932 
0933     void terminate_impl( state_base_type & theState, bool performFullExit )
0934     {
0935       isInnermostCommonOuter_ = false;
0936 
0937       // If pOutermostUnstableState_ == 0, we know for sure that
0938       // currentStates_.size() > 0, otherwise theState couldn't be alive any
0939       // more
0940       if ( get_pointer( pOutermostUnstableState_ ) != 0 )
0941       {
0942         theState.remove_from_state_list(
0943           currentStatesEnd_, pOutermostUnstableState_, performFullExit );
0944       }
0945       // Optimization: We want to find out whether currentStates_ has size 1
0946       // and if yes use the optimized implementation below. Since
0947       // list<>::size() is implemented quite inefficiently in some std libs
0948       // it is best to just decrement the currentStatesEnd_ here and
0949       // increment it again, if the test failed.
0950       else if ( currentStates_.begin() == --currentStatesEnd_ )
0951       {
0952         // The machine is stable and there is exactly one innermost state.
0953         // The following optimization is only correct for a stable machine
0954         // without orthogonal regions.
0955         leaf_state_ptr_type & pState = *currentStatesEnd_;
0956         pState->exit_impl(
0957           pState, pOutermostUnstableState_, performFullExit );
0958       }
0959       else
0960       {
0961         BOOST_ASSERT( currentStates_.size() > 1 );
0962         // The machine is stable and there are multiple innermost states
0963         theState.remove_from_state_list(
0964           ++currentStatesEnd_, pOutermostUnstableState_, performFullExit );
0965       }
0966     }
0967 
0968 
0969     node_state_base_ptr_type add_impl(
0970       const leaf_state_ptr_type & pState,
0971       detail::leaf_state< allocator_type, rtti_policy_type > & )
0972     {
0973       if ( currentStatesEnd_ == currentStates_.end() )
0974       {
0975         pState->set_list_position( 
0976           currentStates_.insert( currentStatesEnd_, pState ) );
0977       }
0978       else
0979       {
0980         *currentStatesEnd_ = pState;
0981         pState->set_list_position( currentStatesEnd_ );
0982         ++currentStatesEnd_;
0983       }
0984 
0985       return 0;
0986     }
0987 
0988     node_state_base_ptr_type add_impl(
0989       const node_state_base_ptr_type & pState,
0990       state_base_type & )
0991     {
0992       return pState;
0993     }
0994 
0995     template< class State >
0996     static bool is_in_highest_orthogonal_region()
0997     {
0998       return mpl::equal_to<
0999         typename State::orthogonal_position,
1000         mpl::minus< 
1001           typename State::context_type::no_of_orthogonal_regions,
1002           mpl::integral_c< detail::orthogonal_position_type, 1 > >
1003       >::value;
1004     }
1005 
1006 
1007     typedef detail::history_key< rtti_policy_type > history_key_type;
1008 
1009     typedef std::map<
1010       history_key_type, void (*)(),
1011       std::less< history_key_type >,
1012       typename boost::detail::allocator::rebind_to<
1013         allocator_type, std::pair< const history_key_type, void (*)() >
1014       >::type
1015     > history_map_type;
1016 
1017     void store_history_impl(
1018       history_map_type & historyMap,
1019       const history_key_type & historyId,
1020       void (*pConstructFunction)() )
1021     {
1022       historyMap[ historyId ] = pConstructFunction;
1023     }
1024 
1025     template< class DefaultState >
1026     void construct_with_history_impl(
1027       history_map_type & historyMap,
1028       const typename DefaultState::context_ptr_type & pContext )
1029     {
1030       typename history_map_type::iterator pFoundSlot = historyMap.find(
1031         history_key_type::make_history_key< DefaultState >() );
1032       
1033       if ( ( pFoundSlot == historyMap.end() ) || ( pFoundSlot->second == 0 ) )
1034       {
1035         // We have never entered this state before or history was cleared
1036         DefaultState::deep_construct(
1037           pContext, *polymorphic_downcast< MostDerived * >( this ) );
1038       }
1039       else
1040       {
1041         typedef void construct_function(
1042           const typename DefaultState::context_ptr_type &,
1043           typename DefaultState::outermost_context_base_type & );
1044         // 5.2.10.6 declares that reinterpret_casting a function pointer to a
1045         // different function pointer and back must yield the same value. The
1046         // following reinterpret_cast is the second half of such a sequence.
1047         construct_function * const pConstructFunction =
1048           reinterpret_cast< construct_function * >( pFoundSlot->second );
1049         (*pConstructFunction)(
1050           pContext, *polymorphic_downcast< MostDerived * >( this ) );
1051       }
1052     }
1053 
1054     typedef std::list<
1055       event_base_ptr_type,
1056       typename boost::detail::allocator::rebind_to<
1057         allocator_type, event_base_ptr_type >::type
1058     > event_queue_type;
1059 
1060     typedef std::map<
1061       const state_base_type *, event_queue_type,
1062       std::less< const state_base_type * >,
1063       typename boost::detail::allocator::rebind_to<
1064         allocator_type,
1065         std::pair< const state_base_type * const, event_queue_type >
1066       >::type
1067     > deferred_map_type;
1068 
1069 
1070     event_queue_type eventQueue_;
1071     event_queue_type deferredEventQueue_;
1072     state_list_type currentStates_;
1073     typename state_list_type::iterator currentStatesEnd_;
1074     state_base_type * pOutermostState_;
1075     bool isInnermostCommonOuter_;
1076     node_state_base_ptr_type pOutermostUnstableState_;
1077     ExceptionTranslator translator_;
1078     bool performFullExit_;
1079     history_map_type shallowHistoryMap_;
1080     history_map_type deepHistoryMap_;
1081     const event_base_type * pTriggeringEvent_;
1082 };
1083 
1084 
1085 
1086 } // namespace statechart
1087 } // namespace boost
1088 
1089 
1090 
1091 #endif