DeferralTest.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. //////////////////////////////////////////////////////////////////////////////
  2. // Copyright 2004-2006 Andreas Huber Doenni
  3. // Distributed under the Boost Software License, Version 1.0. (See accompany-
  4. // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. //////////////////////////////////////////////////////////////////////////////
  6. #include <boost/statechart/state_machine.hpp>
  7. #include <boost/statechart/event.hpp>
  8. #include <boost/statechart/simple_state.hpp>
  9. #include <boost/statechart/transition.hpp>
  10. #include <boost/statechart/deferral.hpp>
  11. #include <boost/statechart/custom_reaction.hpp>
  12. #include <boost/mpl/list.hpp>
  13. #include <boost/intrusive_ptr.hpp>
  14. #include <boost/test/test_tools.hpp>
  15. namespace sc = boost::statechart;
  16. namespace mpl = boost::mpl;
  17. template< class T >
  18. boost::intrusive_ptr< T > MakeIntrusive( T * pT )
  19. {
  20. return boost::intrusive_ptr< T >( pT );
  21. }
  22. struct EvLeafDeferred : sc::event< EvLeafDeferred > {};
  23. struct EvNodeDeferred : sc::event< EvNodeDeferred > {};
  24. struct EvSwitch : sc::event< EvSwitch > {};
  25. struct EvDestroy : sc::event< EvDestroy > {};
  26. struct Active;
  27. struct DeferralTest : sc::state_machine< DeferralTest, Active >
  28. {
  29. //////////////////////////////////////////////////////////////////////////
  30. DeferralTest() : processedCount_( 0 ) {}
  31. void IncrementProcessedCount()
  32. {
  33. ++processedCount_;
  34. }
  35. unsigned int ProcessedCount() const
  36. {
  37. return processedCount_;
  38. }
  39. private:
  40. //////////////////////////////////////////////////////////////////////////
  41. unsigned int processedCount_;
  42. };
  43. struct Dead : sc::simple_state< Dead, DeferralTest >
  44. {
  45. typedef sc::custom_reaction< EvNodeDeferred > reactions;
  46. sc::result react( const EvNodeDeferred & )
  47. {
  48. outermost_context().IncrementProcessedCount();
  49. return discard_event();
  50. }
  51. };
  52. struct Idle;
  53. struct Active : sc::simple_state< Active, DeferralTest, Idle >
  54. {
  55. typedef mpl::list<
  56. sc::custom_reaction< EvLeafDeferred >,
  57. sc::deferral< EvNodeDeferred >,
  58. sc::transition< EvDestroy, Dead >
  59. > reactions;
  60. sc::result react( const EvLeafDeferred & )
  61. {
  62. outermost_context().IncrementProcessedCount();
  63. return discard_event();
  64. }
  65. };
  66. struct Running : sc::simple_state< Running, Active >
  67. {
  68. typedef sc::transition< EvSwitch, Idle > reactions;
  69. };
  70. struct Idle : sc::simple_state< Idle, Active >
  71. {
  72. typedef mpl::list<
  73. sc::transition< EvSwitch, Running >,
  74. sc::deferral< EvLeafDeferred >
  75. > reactions;
  76. };
  77. struct EvToX2 : sc::event< EvToX2 > {};
  78. struct EvToX3 : sc::event< EvToX3 > {};
  79. struct X1;
  80. struct DeferralEventBaseTest : sc::state_machine< DeferralEventBaseTest, X1 >
  81. {
  82. };
  83. struct X3 : sc::simple_state< X3, DeferralEventBaseTest > {};
  84. struct X2 : sc::simple_state< X2, DeferralEventBaseTest >
  85. {
  86. typedef sc::transition< EvToX3, X3 > reactions;
  87. };
  88. struct X1 : sc::simple_state< X1, DeferralEventBaseTest >
  89. {
  90. typedef mpl::list<
  91. sc::transition< EvToX2, X2 >,
  92. sc::deferral< sc::event_base >
  93. > reactions;
  94. };
  95. int test_main( int, char* [] )
  96. {
  97. DeferralTest machine;
  98. machine.initiate();
  99. machine.process_event( *MakeIntrusive( new EvSwitch() ) );
  100. BOOST_REQUIRE( machine.ProcessedCount() == 0 );
  101. machine.process_event( *MakeIntrusive( new EvSwitch() ) );
  102. BOOST_REQUIRE( machine.ProcessedCount() == 0 );
  103. machine.process_event( *MakeIntrusive( new EvLeafDeferred() ) );
  104. BOOST_REQUIRE( machine.ProcessedCount() == 0 );
  105. machine.process_event( *MakeIntrusive( new EvSwitch() ) );
  106. BOOST_REQUIRE( machine.ProcessedCount() == 1 );
  107. machine.process_event( *MakeIntrusive( new EvSwitch() ) );
  108. BOOST_REQUIRE( machine.ProcessedCount() == 1 );
  109. machine.process_event( *MakeIntrusive( new EvLeafDeferred() ) );
  110. machine.process_event( *MakeIntrusive( new EvLeafDeferred() ) );
  111. BOOST_REQUIRE( machine.ProcessedCount() == 1 );
  112. machine.process_event( *MakeIntrusive( new EvSwitch() ) );
  113. BOOST_REQUIRE( machine.ProcessedCount() == 3 );
  114. machine.process_event( *MakeIntrusive( new EvSwitch() ) );
  115. BOOST_REQUIRE( machine.ProcessedCount() == 3 );
  116. machine.process_event( *MakeIntrusive( new EvNodeDeferred() ) );
  117. BOOST_REQUIRE( machine.ProcessedCount() == 3 );
  118. machine.process_event( *MakeIntrusive( new EvSwitch() ) );
  119. BOOST_REQUIRE( machine.ProcessedCount() == 3 );
  120. machine.process_event( EvNodeDeferred() );
  121. BOOST_REQUIRE( machine.ProcessedCount() == 3 );
  122. machine.process_event( *MakeIntrusive( new EvDestroy() ) );
  123. BOOST_REQUIRE( machine.ProcessedCount() == 5 );
  124. DeferralEventBaseTest eventBaseMachine;
  125. // state_cast sanity check
  126. BOOST_REQUIRE_THROW( eventBaseMachine.state_cast< const X1 & >(), std::bad_cast );
  127. eventBaseMachine.initiate();
  128. BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X1 & >() );
  129. // Deferral must work with heap-allocated and stack-allocated events
  130. eventBaseMachine.process_event( EvToX3() );
  131. BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X1 & >() );
  132. eventBaseMachine.process_event( EvToX2() );
  133. BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X3 & >() );
  134. eventBaseMachine.initiate();
  135. BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X1 & >() );
  136. eventBaseMachine.process_event( EvToX2() );
  137. BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X2 & >() );
  138. return 0;
  139. }