My Project
state_machine.hpp
Go to the documentation of this file.
1 #ifndef BOOST_STATECHART_STATE_MACHINE_HPP_INCLUDED
2 #define BOOST_STATECHART_STATE_MACHINE_HPP_INCLUDED
3 // 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)
8 
9 
10 
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/polymorphic_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 
70 template< class StateBaseType, class EventBaseType, class IdType >
72 {
73  public:
76  StateBaseType & toState,
77  const EventBaseType & evt,
78  IdType eventType
79  ) :
80  toState_( toState ), evt_( evt ), eventType_( eventType )
81  {
82  }
83 
85  {
87  toState_.react_impl( evt_, eventType_ ) );
88  }
89 
90  private:
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 
103 {
104  public:
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:
133  template< class IdType, class Type >
134  static IdType type_id_impl( const Type * )
135  {
136  return Type::static_type();
137  }
138 };
139 
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 
177 template< class RttiPolicy >
179 {
180  public:
182  template< class HistorizedState >
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:
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 
231 template< class MostDerived,
232  class InitialState,
233  class Allocator = std::allocator< none >,
234  class ExceptionTranslator = null_exception_translator >
235 class state_machine : noncopyable
236 {
237  public:
239  typedef Allocator allocator_type;
240  typedef detail::rtti_policy rtti_policy_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 );
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 );
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  {
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  {
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 >
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:
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; }
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:
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:
442  // The following declarations should be protected.
443  // They are only public because many compilers lack template friends.
445  template<
446  class HistoryContext,
447  detail::orthogonal_position_type orthogonalPosition >
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 >
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 
492  {
493  return pTriggeringEvent_;
494  }
495 
496  public:
498  // The following declarations should be private.
499  // They are only public because many compilers lack template friends.
501  typedef MostDerived inner_context_type;
502  typedef mpl::integral_c< detail::orthogonal_position_type, 0 >
504  typedef mpl::integral_c< detail::orthogonal_position_type, 1 >
506 
507  typedef MostDerived outermost_context_type;
510  typedef typename state_base_type::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  {
530  }
531 
533  const event_base_type &,
534  typename rtti_policy_type::id_type )
535  {
537  }
538 
539  void exit_impl(
541  typename state_base_type::node_state_base_ptr_type &,
542  bool ) {}
543 
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 
571  {
572  return *polymorphic_downcast< MostDerived * >( this );
573  }
574 
576  {
577  return *polymorphic_downcast< const MostDerived * >( this );
578  }
579 
581  {
582  return *this;
583  }
584 
586  {
587  return *this;
588  }
589 
591  {
592  terminate_impl( theState, performFullExit_ );
593  pOutermostUnstableState_ = 0;
594  }
595 
597  {
598  terminate_impl( theState, performFullExit_ );
599  isInnermostCommonOuter_ = true;
600  }
601 
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 
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 
646  {
647  eventQueue_.splice( eventQueue_.begin(), deferredEventQueue_ );
648  }
649 
650 
651  template< class HistorizedState >
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 >
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 >
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 >
691  const typename DefaultState::context_ptr_type & pContext )
692  {
693  construct_with_history_impl< DefaultState >(
694  deepHistoryMap_, pContext );
695  }
696 
697  private: // implementation
699  void initial_construct()
700  {
701  InitialState::initial_deep_construct(
702  *polymorphic_downcast< MostDerived * >( this ) );
703  }
704 
706  {
707  public:
710  machine_( machine )
711  {
712  }
713 
714  result operator()()
715  {
716  machine_.initial_construct();
718  detail::do_discard_event ); // there is nothing to be consumed
719  }
720 
721  private:
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  };
730 
731  class terminate_function
732  {
733  public:
735  terminate_function( state_machine & machine ) : machine_( machine ) {}
736 
737  result operator()()
738  {
739  machine_.terminate_impl( true );
741  detail::do_discard_event ); // there is nothing to be consumed
742  }
743 
744  private:
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 
802  }
803 
805  {
806  public:
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  {
822  machine_.handle_exception_event(
823  exceptionEvent, pCurrentState_ ) );
824  }
825 
826  private:
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  };
836 
837  class terminator
838  {
839  public:
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:
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();
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_(
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<
1056  typename boost::detail::allocator::rebind_to<
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<
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
boost::statechart::state_machine::set_outermost_unstable_state
void set_outermost_unstable_state(typename state_base_type::node_state_base_ptr_type &pOutermostUnstableState)
Definition: state_machine.hpp:544
boost::statechart::state_machine::leaf_state_ptr_type
state_base_type::leaf_state_ptr_type leaf_state_ptr_type
Definition: state_machine.hpp:512
boost::statechart::state_machine::context_type_list
mpl::clear< mpl::list<> >::type context_type_list
Definition: state_machine.hpp:515
boost::statechart::state_machine::remove_inner_state
void remove_inner_state(detail::orthogonal_position_type position)
Definition: state_machine.hpp:637
boost::statechart::state_machine::clear_shallow_history
void clear_shallow_history()
Definition: state_machine.hpp:448
boost::statechart::state_machine::node_state_base_ptr_type
state_base_type::node_state_base_ptr_type node_state_base_ptr_type
Definition: state_machine.hpp:511
boost::statechart::detail::state_cast_impl_pointer_target
Definition: state_machine.hpp:103
boost::statechart::detail::result_utility::get_result
static reaction_result get_result(::boost::statechart::result value)
Definition: result.hpp:108
boost::statechart::state_machine::state_cast
Target state_cast() const
Definition: state_machine.hpp:284
boost::statechart::state_machine::add
void add(const intrusive_ptr< State > &pState)
Definition: state_machine.hpp:610
boost::statechart::state_machine::inner_context_ptr_type
state_machine * inner_context_ptr_type
Definition: state_machine.hpp:509
boost::statechart::detail::state_cast_impl_pointer_target::type_id
static IdType type_id()
Definition: state_machine.hpp:114
boost::statechart::detail::do_defer_event
@ do_defer_event
Definition: result.hpp:30
boost::statechart::state_machine::state_iterator::operator++
state_iterator & operator++()
Definition: state_machine.hpp:380
boost::statechart::state_machine::shallow_history
mpl::bool_< false > shallow_history
Definition: state_machine.hpp:517
boost::statechart::state_machine::state_machine
state_machine()
Definition: state_machine.hpp:414
boost::statechart::state_machine::construct_with_deep_history
void construct_with_deep_history(const typename DefaultState::context_ptr_type &pContext)
Definition: state_machine.hpp:690
boost::statechart::state_machine::inner_context_type
MostDerived inner_context_type
Definition: state_machine.hpp:501
null_exception_translator.hpp
boost::statechart::state_machine::deep_history
mpl::bool_< false > deep_history
Definition: state_machine.hpp:518
boost::statechart::result
detail::safe_reaction_result result
Definition: result.hpp:91
boost::statechart::state_machine::exception_event_handler
friend class exception_event_handler
Definition: state_machine.hpp:835
boost::statechart::state_machine::exit_impl
void exit_impl(inner_context_ptr_type &, typename state_base_type::node_state_base_ptr_type &, bool)
Definition: state_machine.hpp:539
boost::statechart::state_machine< MostDerived, InitialState, std::allocator< none >, null_exception_translator >::state_base_type
detail::state_base< allocator_type, rtti_policy_type > state_base_type
Definition: state_machine.hpp:357
boost::statechart::state_machine::allocator_type
Allocator allocator_type
Definition: state_machine.hpp:239
boost::statechart::detail::safe_reaction_result
Definition: result.hpp:38
boost::statechart::detail::send_function::operator()
result operator()()
Definition: state_machine.hpp:84
boost::statechart::event_base::intrusive_from_this
intrusive_ptr< const event_base > intrusive_from_this() const
Definition: event_base.hpp:108
event.hpp
boost::statechart::state_machine::state_iterator::state_iterator
state_iterator(typename state_base_type::state_list_type::const_iterator baseIterator)
Definition: state_machine.hpp:369
boost
Definition: asynchronous_state_machine.hpp:20
boost::statechart::detail::send_function
Definition: state_machine.hpp:72
boost::statechart::detail::state_cast_impl
Definition: state_machine.hpp:173
boost::statechart::state_machine::state_iterator::operator*
const state_base_type & operator*() const
Definition: state_machine.hpp:374
boost::statechart::state_machine::construct_with_shallow_history
void construct_with_shallow_history(const typename DefaultState::context_ptr_type &pContext)
Definition: state_machine.hpp:664
boost::statechart::state_machine::triggering_event
const event_base_type * triggering_event() const
Definition: state_machine.hpp:491
boost::statechart::state_machine::inner_orthogonal_position
mpl::integral_c< detail::orthogonal_position_type, 0 > inner_orthogonal_position
Definition: state_machine.hpp:503
boost::statechart::state_machine::terminate_function
friend class terminate_function
Definition: state_machine.hpp:751
boost::statechart::state_machine::outermost_context_base
const outermost_context_base_type & outermost_context_base() const
Definition: state_machine.hpp:585
boost::statechart::state_machine::initial_construct_function
friend class initial_construct_function
Definition: state_machine.hpp:729
boost::statechart::detail::reaction_result
reaction_result
Definition: result.hpp:26
boost::statechart::detail::history_key
Definition: state_machine.hpp:179
boost::statechart::state_machine::rtti_policy_type
detail::rtti_policy rtti_policy_type
Definition: state_machine.hpp:240
boost::statechart::state_machine::inherited_deep_history
mpl::bool_< false > inherited_deep_history
Definition: state_machine.hpp:519
boost::statechart::state_machine::terminate_as_part_of_transit
void terminate_as_part_of_transit(state_machine &)
Definition: state_machine.hpp:602
boost::statechart::detail::state_cast_impl_reference_target::type_id
static IdType type_id()
Definition: state_machine.hpp:150
boost::statechart::state_machine::state_begin
state_iterator state_begin() const
Definition: state_machine.hpp:400
boost::statechart::detail::state_cast_impl_reference_target
Definition: state_machine.hpp:141
boost::statechart::detail::state_cast_impl_pointer_target::deref_if_necessary
static const StateBaseType * deref_if_necessary(const StateBaseType *pState)
Definition: state_machine.hpp:107
boost::statechart::detail::result_utility::make_result
::boost::statechart::result make_result(reaction_result value)
Definition: result.hpp:103
boost::statechart::state_machine::state_iterator::operator==
bool operator==(const state_iterator &right) const
Definition: state_machine.hpp:386
boost::statechart::detail::history_key::operator<
friend bool operator<(const history_key &left, const history_key &right)
Definition: state_machine.hpp:195
boost::statechart::state_machine::no_of_orthogonal_regions
mpl::integral_c< detail::orthogonal_position_type, 1 > no_of_orthogonal_regions
Definition: state_machine.hpp:505
boost::statechart::state_machine::context
Context & context()
Definition: state_machine.hpp:555
boost::statechart::state_machine::store_deep_history
void store_deep_history()
Definition: state_machine.hpp:673
boost::statechart::state_machine::event_base_type
event_base event_base_type
Definition: state_machine.hpp:241
boost::statechart::state_machine::outermost_context
const outermost_context_type & outermost_context() const
Definition: state_machine.hpp:575
boost::statechart::state_machine::state_downcast
Target state_downcast() const
Definition: state_machine.hpp:326
boost::statechart::state_machine::process_event
void process_event(const event_base_type &evt)
Definition: state_machine.hpp:273
boost::statechart::state_machine::unconsumed_event
void unconsumed_event(const event_base &)
Definition: state_machine.hpp:410
boost::statechart::state_machine::outermost_context_type
MostDerived outermost_context_type
Definition: state_machine.hpp:507
boost::statechart::detail::state_cast_impl_reference_target::deref_if_necessary
static const StateBaseType & deref_if_necessary(const StateBaseType *pState)
Definition: state_machine.hpp:143
boost::statechart::state_machine::post_event
void post_event(const event_base &evt)
Definition: state_machine.hpp:435
boost::statechart::state_machine::terminate_as_part_of_transit
void terminate_as_part_of_transit(state_base_type &theState)
Definition: state_machine.hpp:596
boost::statechart::state_machine::store_shallow_history
void store_shallow_history()
Definition: state_machine.hpp:652
boost::statechart::state_machine
Definition: state_machine.hpp:236
boost::statechart::state_machine::react_impl
detail::reaction_result react_impl(const event_base_type &, typename rtti_policy_type::id_type)
Definition: state_machine.hpp:532
boost::statechart::state_machine::release_events
void release_events()
Definition: state_machine.hpp:645
boost::statechart::state_machine::post_event_impl
void post_event_impl(const event_base &evt)
Definition: state_machine.hpp:527
boost::statechart::detail::history_key::make_history_key
static history_key make_history_key()
Definition: state_machine.hpp:183
boost::statechart::state_machine::post_event
void post_event(const event_base_ptr_type &pEvent)
Definition: state_machine.hpp:430
boost::statechart::detail::state_cast_impl_reference_target::not_found
static Target not_found()
Definition: state_machine.hpp:162
boost::statechart::detail::history_key::history_context_type
RttiPolicy::id_type history_context_type() const
Definition: state_machine.hpp:190
boost::statechart::state_machine::terminate
void terminate()
Definition: state_machine.hpp:259
boost::statechart::state_machine::terminator
friend class terminator
Definition: state_machine.hpp:867
boost::statechart::state_machine::context
const Context & context() const
Definition: state_machine.hpp:563
boost::statechart::state_machine::outermost_context
outermost_context_type & outermost_context()
Definition: state_machine.hpp:570
boost::statechart::state_machine::state_iterator::operator!=
bool operator!=(const state_iterator &right) const
Definition: state_machine.hpp:390
boost::statechart::state_machine::~state_machine
virtual ~state_machine()
Definition: state_machine.hpp:425
boost::statechart::event_base
Definition: event_base.hpp:51
boost::statechart::state_machine::post_event_impl
void post_event_impl(const event_base_ptr_type &pEvent)
Definition: state_machine.hpp:521
boost::statechart::state_machine::clear_deep_history
void clear_deep_history()
Definition: state_machine.hpp:471
boost::statechart::state_machine::state_iterator::operator->
const state_base_type * operator->() const
Definition: state_machine.hpp:375
boost::statechart::detail::do_forward_event
@ do_forward_event
Definition: result.hpp:28
boost::statechart::state_machine::outermost_context_base_type
state_machine outermost_context_base_type
Definition: state_machine.hpp:508
boost::statechart::state_machine::state_end
state_iterator state_end() const
Definition: state_machine.hpp:405
boost::statechart::state_machine::outermost_context_base
outermost_context_base_type & outermost_context_base()
Definition: state_machine.hpp:580
boost::statechart::state_machine::initiate
void initiate()
Definition: state_machine.hpp:244
boost::statechart::state_machine::state_list_type
state_base_type::state_list_type state_list_type
Definition: state_machine.hpp:513
boost::statechart::state_machine::terminated
bool terminated() const
Definition: state_machine.hpp:268
boost::statechart::detail::state_cast_impl_pointer_target::not_found
static Target not_found()
Definition: state_machine.hpp:126
boost::statechart::detail::send_function::send_function
send_function(StateBaseType &toState, const EventBaseType &evt, IdType eventType)
Definition: state_machine.hpp:75
boost::statechart::state_machine::add_inner_state
void add_inner_state(detail::orthogonal_position_type position, state_base_type *pOutermostState)
Definition: state_machine.hpp:628
boost::statechart::detail::state_cast_impl_pointer_target::found
static bool found(const void *pFound)
Definition: state_machine.hpp:120
result.hpp
boost::statechart::state_machine::state_iterator
Definition: state_machine.hpp:366
boost::statechart::detail::state_cast_impl_reference_target::found
static bool found(const Dummy &)
Definition: state_machine.hpp:156
boost::statechart::state_machine::terminate_as_reaction
void terminate_as_reaction(state_base_type &theState)
Definition: state_machine.hpp:590
boost::statechart::state_machine::event_base_ptr_type
intrusive_ptr< const event_base_type > event_base_ptr_type
Definition: state_machine.hpp:242
boost::statechart::state_machine::state_iterator::operator++
state_iterator operator++(int)
Definition: state_machine.hpp:381
boost::statechart::detail::do_discard_event
@ do_discard_event
Definition: result.hpp:29