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