]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/statechart/test/DeferralTest.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / statechart / test / DeferralTest.cpp
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
7
8
9 #include <boost/statechart/state_machine.hpp>
10 #include <boost/statechart/event.hpp>
11 #include <boost/statechart/simple_state.hpp>
12 #include <boost/statechart/transition.hpp>
13 #include <boost/statechart/deferral.hpp>
14 #include <boost/statechart/custom_reaction.hpp>
15
16 #include <boost/mpl/list.hpp>
17 #include <boost/intrusive_ptr.hpp>
18
19 #include <boost/test/test_tools.hpp>
20
21
22
23 namespace sc = boost::statechart;
24 namespace mpl = boost::mpl;
25
26
27
28 template< class T >
29 boost::intrusive_ptr< T > MakeIntrusive( T * pT )
30 {
31 return boost::intrusive_ptr< T >( pT );
32 }
33
34 struct EvLeafDeferred : sc::event< EvLeafDeferred > {};
35 struct EvNodeDeferred : sc::event< EvNodeDeferred > {};
36 struct EvSwitch : sc::event< EvSwitch > {};
37 struct EvDestroy : sc::event< EvDestroy > {};
38
39 struct Active;
40 struct DeferralTest : sc::state_machine< DeferralTest, Active >
41 {
42 //////////////////////////////////////////////////////////////////////////
43 DeferralTest() : processedCount_( 0 ) {}
44
45 void IncrementProcessedCount()
46 {
47 ++processedCount_;
48 }
49
50 unsigned int ProcessedCount() const
51 {
52 return processedCount_;
53 }
54
55 private:
56 //////////////////////////////////////////////////////////////////////////
57 unsigned int processedCount_;
58 };
59
60 struct Dead : sc::simple_state< Dead, DeferralTest >
61 {
62 typedef sc::custom_reaction< EvNodeDeferred > reactions;
63
64 sc::result react( const EvNodeDeferred & )
65 {
66 outermost_context().IncrementProcessedCount();
67 return discard_event();
68 }
69 };
70
71 struct Idle;
72 struct Active : sc::simple_state< Active, DeferralTest, Idle >
73 {
74 typedef mpl::list<
75 sc::custom_reaction< EvLeafDeferred >,
76 sc::deferral< EvNodeDeferred >,
77 sc::transition< EvDestroy, Dead >
78 > reactions;
79
80 sc::result react( const EvLeafDeferred & )
81 {
82 outermost_context().IncrementProcessedCount();
83 return discard_event();
84 }
85 };
86
87 struct Running : sc::simple_state< Running, Active >
88 {
89 typedef sc::transition< EvSwitch, Idle > reactions;
90 };
91
92 struct Idle : sc::simple_state< Idle, Active >
93 {
94 typedef mpl::list<
95 sc::transition< EvSwitch, Running >,
96 sc::deferral< EvLeafDeferred >
97 > reactions;
98 };
99
100
101 struct EvToX2 : sc::event< EvToX2 > {};
102 struct EvToX3 : sc::event< EvToX3 > {};
103
104 struct X1;
105 struct DeferralEventBaseTest : sc::state_machine< DeferralEventBaseTest, X1 >
106 {
107 };
108
109 struct X3 : sc::simple_state< X3, DeferralEventBaseTest > {};
110
111 struct X2 : sc::simple_state< X2, DeferralEventBaseTest >
112 {
113 typedef sc::transition< EvToX3, X3 > reactions;
114 };
115
116 struct X1 : sc::simple_state< X1, DeferralEventBaseTest >
117 {
118 typedef mpl::list<
119 sc::transition< EvToX2, X2 >,
120 sc::deferral< sc::event_base >
121 > reactions;
122 };
123
124
125 int test_main( int, char* [] )
126 {
127 DeferralTest machine;
128 machine.initiate();
129 machine.process_event( *MakeIntrusive( new EvSwitch() ) );
130 BOOST_REQUIRE( machine.ProcessedCount() == 0 );
131 machine.process_event( *MakeIntrusive( new EvSwitch() ) );
132 BOOST_REQUIRE( machine.ProcessedCount() == 0 );
133 machine.process_event( *MakeIntrusive( new EvLeafDeferred() ) );
134 BOOST_REQUIRE( machine.ProcessedCount() == 0 );
135 machine.process_event( *MakeIntrusive( new EvSwitch() ) );
136 BOOST_REQUIRE( machine.ProcessedCount() == 1 );
137 machine.process_event( *MakeIntrusive( new EvSwitch() ) );
138 BOOST_REQUIRE( machine.ProcessedCount() == 1 );
139 machine.process_event( *MakeIntrusive( new EvLeafDeferred() ) );
140 machine.process_event( *MakeIntrusive( new EvLeafDeferred() ) );
141 BOOST_REQUIRE( machine.ProcessedCount() == 1 );
142 machine.process_event( *MakeIntrusive( new EvSwitch() ) );
143 BOOST_REQUIRE( machine.ProcessedCount() == 3 );
144 machine.process_event( *MakeIntrusive( new EvSwitch() ) );
145 BOOST_REQUIRE( machine.ProcessedCount() == 3 );
146 machine.process_event( *MakeIntrusive( new EvNodeDeferred() ) );
147 BOOST_REQUIRE( machine.ProcessedCount() == 3 );
148 machine.process_event( *MakeIntrusive( new EvSwitch() ) );
149 BOOST_REQUIRE( machine.ProcessedCount() == 3 );
150 machine.process_event( EvNodeDeferred() );
151 BOOST_REQUIRE( machine.ProcessedCount() == 3 );
152 machine.process_event( *MakeIntrusive( new EvDestroy() ) );
153 BOOST_REQUIRE( machine.ProcessedCount() == 5 );
154
155
156 DeferralEventBaseTest eventBaseMachine;
157 // state_cast sanity check
158 BOOST_REQUIRE_THROW( eventBaseMachine.state_cast< const X1 & >(), std::bad_cast );
159 eventBaseMachine.initiate();
160 BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X1 & >() );
161 // Deferral must work with heap-allocated and stack-allocated events
162 eventBaseMachine.process_event( EvToX3() );
163 BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X1 & >() );
164 eventBaseMachine.process_event( EvToX2() );
165 BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X3 & >() );
166 eventBaseMachine.initiate();
167 BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X1 & >() );
168 eventBaseMachine.process_event( EvToX2() );
169 BOOST_REQUIRE_NO_THROW( eventBaseMachine.state_cast< const X2 & >() );
170
171 return 0;
172 }