Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/statechart/test/FifoSchedulerTest.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 7.3 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2// Copyright 2005-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/asynchronous_state_machine.hpp>
10#include <boost/statechart/fifo_scheduler.hpp>
11#include <boost/statechart/event.hpp>
12#include <boost/statechart/simple_state.hpp>
13#include <boost/statechart/termination.hpp>
14#include <boost/statechart/custom_reaction.hpp>
15
16#include <boost/mpl/list.hpp>
17
18#include <boost/bind.hpp>
19#include <boost/ref.hpp>
20
21#include <boost/test/test_tools.hpp>
22
23#include <stdexcept>
24
25
26
27namespace sc = boost::statechart;
28namespace mpl = boost::mpl;
29
30
31
32struct EvCheckCtorArgs : sc::event< EvCheckCtorArgs >
33{
34  EvCheckCtorArgs( int expectedArgs ) : expectedArgs_( expectedArgs ) {}
35  const int expectedArgs_;
36};
37
38struct EvTerminate : sc::event< EvTerminate > {};
39struct EvFail : sc::event< EvFail > {};
40
41
42struct Initial;
43struct FifoSchedulerTest :
44  sc::asynchronous_state_machine< FifoSchedulerTest, Initial >
45{
46  public:
47    //////////////////////////////////////////////////////////////////////////
48    FifoSchedulerTest( my_context ctx ) :
49      my_base( ctx ),
50      ctorArgs_( 0 )
51    {
52    }
53
54    FifoSchedulerTest( my_context ctx, int arg1 ) :
55      my_base( ctx ),
56      ctorArgs_( arg1 )
57    {
58    }
59
60    FifoSchedulerTest( my_context ctx, int arg1, int arg2 ) :
61      my_base( ctx ),
62      ctorArgs_( arg1 * 10 + arg2 )
63    {
64    }
65
66    FifoSchedulerTest( my_context ctx, int arg1, int arg2, int arg3 ) :
67      my_base( ctx ),
68      ctorArgs_( ( arg1 * 10 + arg2 ) * 10 + arg3 )
69    {
70    }
71
72    FifoSchedulerTest(
73      my_context ctx,
74      int arg1, int arg2, int arg3, int arg4
75    ) :
76      my_base( ctx ),
77      ctorArgs_( ( ( arg1 * 10 + arg2 ) * 10 + arg3 ) * 10 + arg4 )
78    {
79    }
80
81    FifoSchedulerTest(
82      my_context ctx,
83      int arg1, int arg2, int arg3, int arg4, int arg5
84    ) :
85      my_base( ctx ),
86      ctorArgs_( ( ( ( arg1 * 10 + arg2 ) * 10 +
87        arg3 ) * 10 + arg4 ) * 10 + arg5 )
88    {
89    }
90
91    FifoSchedulerTest(
92      my_context ctx,
93      int arg1, int arg2, int arg3, int arg4, int arg5, int arg6
94    ) :
95      my_base( ctx ),
96      ctorArgs_( ( ( ( ( arg1 * 10 + arg2 ) * 10 +
97        arg3 ) * 10 + arg4 ) * 10 + arg5 ) * 10 + arg6 )
98    {
99    }
100
101    int CtorArgs()
102    {
103      return ctorArgs_;
104    }
105
106  private:
107    //////////////////////////////////////////////////////////////////////////
108    const int ctorArgs_;
109};
110
111boost::intrusive_ptr< const sc::event_base > MakeEvent(
112  const sc::event_base * pEvent )
113{
114  return boost::intrusive_ptr< const sc::event_base >( pEvent );
115}
116
117struct Initial : sc::simple_state< Initial, FifoSchedulerTest >
118{
119  typedef mpl::list<
120    sc::custom_reaction< EvCheckCtorArgs >,
121    sc::termination< EvTerminate >,
122    sc::custom_reaction< EvFail >
123  > reactions;
124
125  sc::result react( const EvCheckCtorArgs & ev )
126  {
127    BOOST_REQUIRE( ev.expectedArgs_ == outermost_context().CtorArgs() );
128    outermost_context_type & machine = outermost_context();
129    machine.my_scheduler().queue_event(
130      machine.my_handle(), MakeEvent( new EvTerminate() ) );
131    return discard_event();
132  }
133
134  sc::result react( const EvFail & )
135  {
136    BOOST_FAIL( "State machine is unexpectedly still running." );
137    return discard_event();
138  }
139};
140
141
142struct UnexpectedEventCount : public std::runtime_error
143{
144  UnexpectedEventCount() : std::runtime_error( "" ) {}
145};
146
147void RunScheduler(
148  sc::fifo_scheduler<> & scheduler, unsigned long expectedEventCount )
149{
150  // Workaround: For some reason MSVC has a problem with BOOST_REQUIRE here
151  // (C1055: compiler limit: out of keys)
152  if ( scheduler() != expectedEventCount )
153  {
154    throw UnexpectedEventCount();
155  }
156}
157
158void Check(
159  sc::fifo_scheduler<> & scheduler,
160  const sc::fifo_scheduler<>::processor_handle & processor,
161  int ctorArgs )
162{
163  // Make sure the processor has been created
164  RunScheduler( scheduler, 1UL );
165
166  scheduler.initiate_processor( processor );
167  // This event triggers the queueing of another event, which itself
168  // terminates the machine ...
169  scheduler.queue_event(
170    processor, MakeEvent( new EvCheckCtorArgs( ctorArgs ) ) );
171  // ... that's why 3 instead of two events must have been processed
172  RunScheduler( scheduler, 3UL );
173
174  // Since the machine has been terminated, this event will be ignored
175  scheduler.queue_event( processor, MakeEvent( new EvFail() ) );
176  RunScheduler( scheduler, 1UL );
177
178  // Check that we can reinitiate the machine
179  scheduler.initiate_processor( processor );
180  scheduler.queue_event(
181    processor, MakeEvent( new EvCheckCtorArgs( ctorArgs ) ) );
182  RunScheduler( scheduler, 3UL );
183
184  // Check that we are terminated again
185  scheduler.queue_event( processor, MakeEvent( new EvFail() ) );
186  RunScheduler( scheduler, 1UL );
187
188  scheduler.destroy_processor( processor );
189  // The following will simply be ignored because the processor has already
190  // be destroyed
191  scheduler.initiate_processor( processor );
192  scheduler.queue_event(
193    processor, MakeEvent( new EvCheckCtorArgs( ctorArgs ) ) );
194  RunScheduler( scheduler, 3UL );
195}
196
197void SetToTrue( bool & value )
198{
199  value = true;
200}
201
202int test_main( int, char* [] )
203{
204  try
205  {
206    sc::fifo_scheduler<> scheduler;
207    const sc::fifo_scheduler<>::processor_handle processor0 =
208      scheduler.create_processor< FifoSchedulerTest >();
209    Check( scheduler, processor0, 0 );
210
211    const sc::fifo_scheduler<>::processor_handle processor1 =
212      scheduler.create_processor< FifoSchedulerTest >( 1 );
213    Check( scheduler, processor1, 1 );
214
215    const sc::fifo_scheduler<>::processor_handle processor2 =
216      scheduler.create_processor< FifoSchedulerTest >( 1, 2 );
217    Check( scheduler, processor2, 12 );
218
219    const sc::fifo_scheduler<>::processor_handle processor3 =
220      scheduler.create_processor< FifoSchedulerTest >( 1, 2, 3 );
221    Check( scheduler, processor3, 123 );
222
223    const sc::fifo_scheduler<>::processor_handle processor4 =
224      scheduler.create_processor< FifoSchedulerTest >( 1, 2, 3, 4 );
225    Check( scheduler, processor4, 1234 );
226
227    const sc::fifo_scheduler<>::processor_handle processor5 =
228      scheduler.create_processor< FifoSchedulerTest >( 1, 2, 3, 4, 5 );
229    Check( scheduler, processor5, 12345 );
230
231    const sc::fifo_scheduler<>::processor_handle processor6 =
232      scheduler.create_processor< FifoSchedulerTest >( 1, 2, 3, 4, 5, 6 );
233    Check( scheduler, processor6, 123456 );
234
235    RunScheduler( scheduler, 0UL );
236    bool workItem1Processed = false;
237    scheduler.queue_work_item(
238      boost::bind( &SetToTrue, boost::ref( workItem1Processed ) ) );
239    RunScheduler( scheduler, 1UL );
240    BOOST_REQUIRE( workItem1Processed );
241
242    scheduler.terminate();
243    RunScheduler( scheduler, 1UL );
244    BOOST_REQUIRE( scheduler.terminated() );
245
246    RunScheduler( scheduler, 0UL );
247    bool workItem2Processed = false;
248    scheduler.queue_work_item(
249      boost::bind( &SetToTrue, boost::ref( workItem2Processed ) ) );
250    // After being terminated, a call to operator() must not process any more
251    // events
252    RunScheduler( scheduler, 0UL );
253    BOOST_REQUIRE( !workItem2Processed );
254  }
255  catch ( const UnexpectedEventCount & )
256  {
257    BOOST_FAIL( "Unexpected event count." );
258  }
259
260  return 0;
261}
Note: See TracBrowser for help on using the repository browser.