Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / ACE / tests / MT_Reactor_Timer_Test.cpp
blob6b952c9d5d06471d6ab95b5d43637a11718ea8d0
2 //=============================================================================
3 /**
4 * @file MT_Reactor_Timer_Test.cpp
6 * This is a simple test that illustrates the timer mechanism of
7 * the reactor scheduling timers, handling expired timers and
8 * cancelling scheduled timers from multiple threads. No command
9 * line arguments are needed to run the test.
11 * @author Steve Huston <shuston@riverace.com>
13 //=============================================================================
16 #include "test_config.h"
17 #include "MT_Reactor_Timer_Test.h"
18 #include "ace/ACE.h"
19 #include "ace/OS_NS_unistd.h"
22 #if defined (ACE_HAS_THREADS)
24 // This test exercises the setting and cancelling of timers from a
25 // thread other than the one the reactor is running in. It sets up an
26 // initial set of timers (3, 4, 5 seconds) from the main thread. When
27 // the second thread starts, it cancels the 3 second timer and sets a
28 // 2-second timer and an already-expired timer, which should be the
29 // first to fire. It then sleeps for 3 seconds (letting the 2 second
30 // timer fire, and if things are slow, the 4 second timer will also
31 // fire. Then it sets 2 more timers at 10 and 12 seconds and cancels
32 // the original 5 second timer. Then returns, ending the thread. The
33 // destructor for Time_Handler insures that everything happened
34 // correctly.
36 Time_Handler::Time_Handler ()
38 for (int i = 0;
39 i < Time_Handler::TIMER_SLOTS;
40 this->timer_id_[i++] = Time_Handler::TIMER_NOTSET)
41 continue;
43 this->prev_timer_ = -1;
46 // Set up initial timer conditions. Timers set up at 3, 4, and 5
47 // seconds. The one at 3 seconds will get cancelled when the thread
48 // starts.
50 void
51 Time_Handler::setup ()
53 ACE_Reactor *r = ACE_Reactor::instance ();
55 this->timer_id_[2] = r->schedule_timer (this,
56 (const void *) 2,
57 ACE_Time_Value (3));
58 this->timer_id_[3] = r->schedule_timer (this,
59 (const void *) 3,
60 ACE_Time_Value (4));
61 this->timer_id_[4] = r->schedule_timer (this,
62 (const void *) 4,
63 ACE_Time_Value (5));
64 return;
67 int
68 Time_Handler::verify_results ()
70 ACE_TEST_ASSERT (this->timer_id_[0] == Time_Handler::TIMER_FIRED);
71 ACE_TEST_ASSERT (this->timer_id_[1] == Time_Handler::TIMER_FIRED);
72 ACE_TEST_ASSERT (this->timer_id_[2] == Time_Handler::TIMER_CANCELLED);
73 ACE_TEST_ASSERT (this->timer_id_[3] == Time_Handler::TIMER_FIRED);
74 ACE_TEST_ASSERT (this->timer_id_[4] == Time_Handler::TIMER_CANCELLED);
75 ACE_TEST_ASSERT (this->timer_id_[5] == Time_Handler::TIMER_FIRED);
76 ACE_TEST_ASSERT (this->timer_id_[6] == Time_Handler::TIMER_FIRED);
78 for (int i = 7; i < Time_Handler::TIMER_SLOTS; i++)
79 ACE_TEST_ASSERT (this->timer_id_[i] == Time_Handler::TIMER_NOTSET);
81 return 0;
84 int
85 Time_Handler::svc ()
87 ACE_Reactor *r = ACE_Reactor::instance ();
89 ACE_TEST_ASSERT (r->cancel_timer (this->timer_id_[2]) == 1);
90 this->timer_id_[2] = Time_Handler::TIMER_CANCELLED;
92 this->timer_id_[1] = r->schedule_timer(this,
93 (const void *) 1,
94 ACE_Time_Value (2));
95 // This one may get the callback before we return, so serialize.
96 this->lock_.acquire ();
97 this->timer_id_[0] = r->schedule_timer(this,
98 (const void *) 0,
99 ACE_Time_Value (0, -5));
100 this->lock_.release ();
101 ACE_OS::sleep(3);
103 this->timer_id_[5] = r->schedule_timer(this,
104 (const void *)5,
105 ACE_Time_Value (10));
106 this->timer_id_[6] = r->schedule_timer(this,
107 (const void *)6,
108 ACE_Time_Value (12));
110 ACE_TEST_ASSERT (r->cancel_timer (this->timer_id_[4]) == 1);
111 this->timer_id_[4] = Time_Handler::TIMER_CANCELLED;
113 // Test that cancelling a timers through a nill ACE_Event_Handler
114 // pointer just does nothing instead of crash
115 ACE_Event_Handler_var timer_var;
116 ACE_TEST_ASSERT (r->cancel_timer (timer_var.handler()) == 0);
118 return 0;
122 Time_Handler::handle_timeout (const ACE_Time_Value &tv,
123 const void *arg)
125 long time_tag = static_cast <long> (reinterpret_cast <size_t> (arg));
126 ACE_UNUSED_ARG(tv);
128 ACE_GUARD_RETURN (ACE_Thread_Mutex, id_lock, this->lock_, 0);
130 ACE_DEBUG ((LM_DEBUG,
131 ACE_TEXT ("%T (%t): Timer #%d (id #%d) expired\n"),
132 time_tag,
133 this->timer_id_[time_tag]));
135 ACE_TEST_ASSERT (time_tag > this->prev_timer_);
136 ACE_TEST_ASSERT (this->timer_id_[time_tag] != Time_Handler::TIMER_NOTSET);
137 ACE_TEST_ASSERT (this->timer_id_[time_tag] != Time_Handler::TIMER_CANCELLED);
138 ACE_TEST_ASSERT (this->timer_id_[time_tag] != Time_Handler::TIMER_FIRED);
139 this->timer_id_[time_tag] = Time_Handler::TIMER_FIRED;
140 this->prev_timer_ = time_tag;
142 return 0;
145 #endif /* ACE_HAS_THREADS */
147 Dispatch_Count_Handler::Dispatch_Count_Handler ()
149 ACE_Reactor *r = ACE_Reactor::instance ();
151 this->input_seen_ = this->notify_seen_ = 0;
152 this->timers_fired_ = 0;
154 // Initialize the pipe.
155 if (this->pipe_.open () == -1)
156 ACE_ERROR ((LM_ERROR,
157 ACE_TEXT ("%p\n"),
158 ACE_TEXT ("ACE_Pipe::open")));
159 // Register the "read" end of the pipe.
160 else if (r->register_handler (this->pipe_.read_handle (),
161 this,
162 ACE_Event_Handler::READ_MASK) == -1)
163 ACE_ERROR ((LM_ERROR,
164 ACE_TEXT ("%p\n"),
165 ACE_TEXT ("register_handler")));
166 // Put something in our pipe and smoke it... ;-)
167 else if (ACE::send (this->pipe_.write_handle (),
168 "z",
169 1) == -1)
170 ACE_ERROR ((LM_ERROR,
171 ACE_TEXT ("%p\n"),
172 ACE_TEXT ("send")));
173 // Call notify to prime the pump for this, as well.
174 else if (r->notify (this) == -1)
175 ACE_ERROR ((LM_ERROR,
176 ACE_TEXT ("%p\n"),
177 ACE_TEXT ("notify")));
181 Dispatch_Count_Handler::handle_close (ACE_HANDLE h,
182 ACE_Reactor_Mask m)
184 ACE_DEBUG ((LM_DEBUG,
185 ACE_TEXT ("%T (%t): handle_close\n")));
187 ACE_TEST_ASSERT (h == this->pipe_.read_handle ()
188 && m == ACE_Event_Handler::READ_MASK);
190 return 0;
194 Dispatch_Count_Handler::handle_input (ACE_HANDLE h)
196 char c;
198 ACE_TEST_ASSERT (this->input_seen_ == 0);
199 this->input_seen_ = 1;
201 if (ACE::recv (h, &c, 1) != 1)
202 ACE_ERROR_RETURN ((LM_ERROR,
203 ACE_TEXT ("%p\n"),
204 ACE_TEXT ("recv")),
205 -1);
207 ACE_TEST_ASSERT (c == 'z');
208 ACE_DEBUG ((LM_DEBUG,
209 ACE_TEXT ("%T (%t): handle_input\n")));
210 // Trigger the <handle_close> hook.
211 return -1;
215 Dispatch_Count_Handler::handle_exception (ACE_HANDLE h)
217 ACE_UNUSED_ARG (h);
219 ACE_TEST_ASSERT (this->notify_seen_ == 0);
220 this->notify_seen_ = 1;
222 ACE_DEBUG ((LM_DEBUG,
223 ACE_TEXT ("%T (%t): handle_exception\n")));
224 return 0;
228 Dispatch_Count_Handler::handle_timeout (const ACE_Time_Value &tv,
229 const void *arg)
231 ACE_UNUSED_ARG (tv);
233 ++this->timers_fired_;
235 long value = static_cast <long> (reinterpret_cast <size_t> (arg));
237 // This case just tests to make sure the Reactor is counting timer
238 // expiration correctly.
239 ACE_DEBUG ((LM_DEBUG,
240 ACE_TEXT ("%T (%t): expiration %d\n"),
241 value));
242 return 0;
246 Dispatch_Count_Handler::verify_results ()
248 int result = 0;
250 if (this->input_seen_ != 1)
252 ACE_ERROR ((LM_ERROR,
253 ACE_TEXT ("input_seen_ is not 1 but %d\n"),
254 input_seen_));
255 result = -1;
258 if (this->notify_seen_ != 1)
260 ACE_ERROR ((LM_ERROR,
261 ACE_TEXT ("notify_seen_ is not 1 but %d\n"),
262 notify_seen_));
263 result = -1;
266 if (this->timers_fired_ != ACE_MAX_TIMERS)
268 ACE_ERROR ((LM_ERROR,
269 ACE_TEXT ("timers fired not equal max timers: %d != %d\n"),
270 this->timers_fired_,
271 ACE_MAX_TIMERS));
272 result = -1;
275 return result;
279 run_main (int, ACE_TCHAR *[])
281 ACE_START_TEST (ACE_TEXT ("MT_Reactor_Timer_Test"));
283 int status = 0;
284 int test_result = 0;
286 ACE_Reactor *r = ACE_Reactor::instance ();
288 Dispatch_Count_Handler callback;
290 for (int i = ACE_MAX_TIMERS; i > 0; i--)
291 // Schedule a timeout to expire immediately.
292 if (r->schedule_timer (&callback,
293 reinterpret_cast <const void *> (static_cast <size_t> (i)),
294 ACE_Time_Value (0)) == -1)
295 ACE_ERROR_RETURN ((LM_ERROR,
296 ACE_TEXT ("%p\n"),
297 ACE_TEXT ("schedule_timer")),
300 ACE_Time_Value no_waiting (0);
301 size_t events = 0;
303 while (1)
305 int result = r->handle_events (no_waiting);
307 // Timeout.
308 if (result == 0)
309 break;
311 // Make sure there were no errors.
312 ACE_TEST_ASSERT (result != -1);
314 events += result;
317 // All <ACE_MAX_TIMERS> + 2 I/O dispatches (one for <handle_input>
318 // and the other for <handle_exception>) should be counted in
319 // events.
320 if (events < ACE_MAX_TIMERS + 2)
322 ACE_ERROR ((LM_ERROR,
323 ACE_TEXT ("expected %d events, got %d instead\n"),
324 ACE_MAX_TIMERS + 2,
325 events));
328 status = callback.verify_results ();
329 if (status != 0)
331 ACE_ERROR ((LM_ERROR,
332 ACE_TEXT ("Dispatch counting test failed.\n")));
333 test_result = 1;
336 #if defined (ACE_HAS_THREADS)
338 Time_Handler other_thread;
339 ACE_Time_Value time_limit (30);
341 // Set up initial set of timers.
342 other_thread.setup ();
344 other_thread.activate (THR_NEW_LWP | THR_JOINABLE);
345 status = ACE_Reactor::instance()->run_reactor_event_loop (time_limit);
346 // Should have returned only because the time limit is up...
347 ACE_TEST_ASSERT (status != -1);
348 ACE_TEST_ASSERT (time_limit.sec () == 0);
350 status = other_thread.wait ();
351 if (status == -1)
353 ACE_ERROR ((LM_ERROR,
354 ACE_TEXT ("%p, errno is %d\n"),
355 "wait ()",
356 ACE_ERRNO_GET));
357 ACE_TEST_ASSERT (status != -1);
360 status = other_thread.verify_results ();
361 if (status != 0)
362 test_result = 1;
364 #else
365 ACE_ERROR ((LM_INFO,
366 ACE_TEXT ("threads not supported on this platform\n")));
367 #endif /* ACE_HAS_THREADS */
369 ACE_END_TEST;
370 return test_result;