state_base.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #ifndef BOOST_STATECHART_DETAIL_STATE_BASE_HPP_INCLUDED
  2. #define BOOST_STATECHART_DETAIL_STATE_BASE_HPP_INCLUDED
  3. //////////////////////////////////////////////////////////////////////////////
  4. // Copyright 2002-2008 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/result.hpp>
  9. #include <boost/statechart/event.hpp>
  10. #include <boost/statechart/detail/counted_base.hpp>
  11. #include <boost/intrusive_ptr.hpp>
  12. #include <boost/noncopyable.hpp>
  13. #include <boost/assert.hpp>
  14. #include <boost/config.hpp> // BOOST_MSVC
  15. #include <boost/detail/workaround.hpp>
  16. #include <boost/detail/allocator_utilities.hpp>
  17. #ifdef BOOST_MSVC
  18. # pragma warning( push )
  19. # pragma warning( disable: 4702 ) // unreachable code (in release mode only)
  20. #endif
  21. #include <list>
  22. #ifdef BOOST_MSVC
  23. # pragma warning( pop )
  24. #endif
  25. namespace boost
  26. {
  27. namespace statechart
  28. {
  29. namespace detail
  30. {
  31. template< class Allocator, class RttiPolicy >
  32. class leaf_state;
  33. template< class Allocator, class RttiPolicy >
  34. class node_state_base;
  35. typedef unsigned char orthogonal_position_type;
  36. //////////////////////////////////////////////////////////////////////////////
  37. template< class Allocator, class RttiPolicy >
  38. class state_base :
  39. #ifndef NDEBUG
  40. noncopyable,
  41. #endif
  42. public RttiPolicy::template rtti_base_type<
  43. // Derived class objects will be created, handled and destroyed by exactly
  44. // one thread --> locking is not necessary
  45. counted_base< false > >
  46. {
  47. typedef typename RttiPolicy::template rtti_base_type<
  48. counted_base< false > > base_type;
  49. public:
  50. //////////////////////////////////////////////////////////////////////////
  51. void exit() {}
  52. virtual const state_base * outer_state_ptr() const = 0;
  53. protected:
  54. //////////////////////////////////////////////////////////////////////////
  55. state_base( typename RttiPolicy::id_provider_type idProvider ) :
  56. base_type( idProvider ),
  57. deferredEvents_( false )
  58. {
  59. }
  60. #if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT( 4 ) )
  61. // We make the destructor virtual for GCC because with this compiler there
  62. // is currently no way to disable the "has virtual functions but
  63. // non-virtual destructor" warning on a class by class basis. Although it
  64. // can be done on the compiler command line with -Wno-non-virtual-dtor,
  65. // this is undesirable as this would also suppress legitimate warnings for
  66. // types that are not states.
  67. virtual ~state_base() {}
  68. #else
  69. // This destructor is not virtual for performance reasons. The library
  70. // ensures that a state object is never deleted through a state_base
  71. // pointer but only through a pointer to the most-derived type.
  72. ~state_base() {}
  73. #endif
  74. protected:
  75. //////////////////////////////////////////////////////////////////////////
  76. // The following declarations should be private.
  77. // They are only protected because many compilers lack template friends.
  78. //////////////////////////////////////////////////////////////////////////
  79. void defer_event()
  80. {
  81. deferredEvents_ = true;
  82. }
  83. bool deferred_events() const
  84. {
  85. return deferredEvents_;
  86. }
  87. template< class Context >
  88. void set_context( orthogonal_position_type position, Context * pContext )
  89. {
  90. pContext->add_inner_state( position, this );
  91. }
  92. public:
  93. //////////////////////////////////////////////////////////////////////////
  94. // The following declarations should be private.
  95. // They are only public because many compilers lack template friends.
  96. //////////////////////////////////////////////////////////////////////////
  97. virtual detail::reaction_result react_impl(
  98. const event_base & evt,
  99. typename RttiPolicy::id_type eventType ) = 0;
  100. typedef intrusive_ptr< node_state_base< Allocator, RttiPolicy > >
  101. node_state_base_ptr_type;
  102. typedef intrusive_ptr< leaf_state< Allocator, RttiPolicy > >
  103. leaf_state_ptr_type;
  104. typedef std::list<
  105. leaf_state_ptr_type,
  106. typename boost::detail::allocator::rebind_to<
  107. Allocator, leaf_state_ptr_type >::type
  108. > state_list_type;
  109. virtual void remove_from_state_list(
  110. typename state_list_type::iterator & statesEnd,
  111. node_state_base_ptr_type & pOutermostUnstableState,
  112. bool performFullExit ) = 0;
  113. private:
  114. //////////////////////////////////////////////////////////////////////////
  115. bool deferredEvents_;
  116. };
  117. #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
  118. } // namespace detail
  119. } // namespace statechart
  120. #endif
  121. template< class Allocator, class RttiPolicy >
  122. inline void intrusive_ptr_add_ref(
  123. const ::boost::statechart::detail::state_base< Allocator, RttiPolicy > * pBase )
  124. {
  125. pBase->add_ref();
  126. }
  127. template< class Allocator, class RttiPolicy >
  128. inline void intrusive_ptr_release(
  129. const ::boost::statechart::detail::state_base< Allocator, RttiPolicy > * pBase )
  130. {
  131. if ( pBase->release() )
  132. {
  133. // The state_base destructor is *not* virtual for performance reasons
  134. // but intrusive_ptr< state_base > objects are nevertheless used to point
  135. // to states. This assert ensures that such a pointer is never the last
  136. // one referencing a state object.
  137. BOOST_ASSERT( false );
  138. }
  139. }
  140. #ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
  141. } // namespace detail
  142. } // namespace statechart
  143. #endif
  144. } // namespace boost
  145. #endif