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