node_state.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #ifndef BOOST_STATECHART_DETAIL_NODE_STATE_HPP_INCLUDED
  2. #define BOOST_STATECHART_DETAIL_NODE_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. #include <boost/statechart/detail/state_base.hpp>
  9. #include <boost/intrusive_ptr.hpp>
  10. #include <boost/assert.hpp> // BOOST_ASSERT
  11. #include <algorithm> // std::find_if
  12. namespace boost
  13. {
  14. namespace statechart
  15. {
  16. namespace detail
  17. {
  18. template< class Allocator, class RttiPolicy >
  19. class node_state_base : public state_base< Allocator, RttiPolicy >
  20. {
  21. typedef state_base< Allocator, RttiPolicy > base_type;
  22. protected:
  23. //////////////////////////////////////////////////////////////////////////
  24. node_state_base( typename RttiPolicy::id_provider_type idProvider ) :
  25. base_type( idProvider )
  26. {
  27. }
  28. ~node_state_base() {}
  29. public:
  30. //////////////////////////////////////////////////////////////////////////
  31. // The following declarations should be private.
  32. // They are only public because many compilers lack template friends.
  33. //////////////////////////////////////////////////////////////////////////
  34. typedef base_type state_base_type;
  35. typedef intrusive_ptr< node_state_base > direct_state_base_ptr_type;
  36. virtual void exit_impl(
  37. direct_state_base_ptr_type & pSelf,
  38. typename base_type::node_state_base_ptr_type & pOutermostUnstableState,
  39. bool performFullExit ) = 0;
  40. };
  41. //////////////////////////////////////////////////////////////////////////////
  42. template< class OrthogonalRegionCount, class Allocator, class RttiPolicy >
  43. class node_state : public node_state_base< Allocator, RttiPolicy >
  44. {
  45. typedef node_state_base< Allocator, RttiPolicy > base_type;
  46. protected:
  47. //////////////////////////////////////////////////////////////////////////
  48. node_state( typename RttiPolicy::id_provider_type idProvider ) :
  49. base_type( idProvider )
  50. {
  51. for ( orthogonal_position_type pos = 0;
  52. pos < OrthogonalRegionCount::value; ++pos )
  53. {
  54. pInnerStates[ pos ] = 0;
  55. }
  56. }
  57. ~node_state() {}
  58. public:
  59. //////////////////////////////////////////////////////////////////////////
  60. // The following declarations should be private.
  61. // They are only public because many compilers lack template friends.
  62. //////////////////////////////////////////////////////////////////////////
  63. typedef typename base_type::state_base_type state_base_type;
  64. void add_inner_state( orthogonal_position_type position,
  65. state_base_type * pInnerState )
  66. {
  67. BOOST_ASSERT( ( position < OrthogonalRegionCount::value ) &&
  68. ( pInnerStates[ position ] == 0 ) );
  69. pInnerStates[ position ] = pInnerState;
  70. }
  71. void remove_inner_state( orthogonal_position_type position )
  72. {
  73. BOOST_ASSERT( position < OrthogonalRegionCount::value );
  74. pInnerStates[ position ] = 0;
  75. }
  76. virtual void remove_from_state_list(
  77. typename state_base_type::state_list_type::iterator & statesEnd,
  78. typename state_base_type::node_state_base_ptr_type &
  79. pOutermostUnstableState,
  80. bool performFullExit )
  81. {
  82. state_base_type ** const pPastEnd =
  83. &pInnerStates[ OrthogonalRegionCount::value ];
  84. // We must not iterate past the last inner state because *this* state
  85. // will no longer exist when the last inner state has been removed
  86. state_base_type ** const pFirstNonNull = std::find_if(
  87. &pInnerStates[ 0 ], pPastEnd, &node_state::is_not_null );
  88. if ( pFirstNonNull == pPastEnd )
  89. {
  90. // The state does not have inner states but is still alive, this must
  91. // be the outermost unstable state then.
  92. BOOST_ASSERT( get_pointer( pOutermostUnstableState ) == this );
  93. typename state_base_type::node_state_base_ptr_type pSelf =
  94. pOutermostUnstableState;
  95. pSelf->exit_impl( pSelf, pOutermostUnstableState, performFullExit );
  96. }
  97. else
  98. {
  99. // Destroy inner states in the reverse order of construction
  100. for ( state_base_type ** pState = pPastEnd; pState != pFirstNonNull; )
  101. {
  102. --pState;
  103. // An inner orthogonal state might have been terminated long before,
  104. // that's why we have to check for 0 pointers
  105. if ( *pState != 0 )
  106. {
  107. ( *pState )->remove_from_state_list(
  108. statesEnd, pOutermostUnstableState, performFullExit );
  109. }
  110. }
  111. }
  112. }
  113. typedef typename base_type::direct_state_base_ptr_type
  114. direct_state_base_ptr_type;
  115. private:
  116. //////////////////////////////////////////////////////////////////////////
  117. static bool is_not_null( const state_base_type * pInner )
  118. {
  119. return pInner != 0;
  120. }
  121. state_base_type * pInnerStates[ OrthogonalRegionCount::value ];
  122. };
  123. } // namespace detail
  124. } // namespace statechart
  125. } // namespace boost
  126. #endif