Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/statechart/simple_state.hpp @ 56

Last change on this file since 56 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

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