1 //=============================================================================
3 * @file Reactor_Timer_Test.cpp
5 * This is a simple test that illustrates the timer mechanism of
6 * the reactor. Scheduling timers, resetting timer intervals,
7 * handling expired timers and cancelling scheduled timers are
8 * all exercised in this test.
10 * @author Prashant Jain <pjain@cs.wustl.edu> and Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
12 //=============================================================================
14 #include "test_config.h"
15 #include "ace/Timer_Queue.h"
16 #include "ace/Reactor.h"
17 #include "ace/High_Res_Timer.h"
18 #include "ace/Trace.h"
19 #include "ace/Recursive_Thread_Mutex.h"
20 #include "ace/Log_Msg.h"
21 #include "ace/Timer_Heap.h"
25 static int the_count
= 0;
28 class Time_Handler
: public ACE_Event_Handler
31 /// Default constructor
34 /// Handle the timeout.
35 int handle_timeout (const ACE_Time_Value
&tv
,
36 const void *arg
) override
;
38 /// Called when <Time_Handler> is removed.
39 int handle_close (ACE_HANDLE handle
,
40 ACE_Reactor_Mask close_mask
) override
;
42 /// Return our timer id.
43 long timer_id () const;
49 /// Stores the id of this timer.
53 Time_Handler::Time_Handler ()
60 Time_Handler::handle_close (ACE_HANDLE handle
,
61 ACE_Reactor_Mask close_mask
)
64 ACE_TEXT ("[%x] handle = %d, close_mask = %d, timer id = %d\n"),
73 Time_Handler::handle_timeout (const ACE_Time_Value
&tv
,
76 long current_count
= static_cast<long> (reinterpret_cast<size_t> (arg
));
77 if (current_count
>= 0)
78 ACE_TEST_ASSERT (current_count
== the_count
);
81 ACE_TEXT ("[%x] Timer id %d with count #%d|%d timed out at %d!\n"),
88 if (current_count
== long (ACE_MAX_TIMERS
- 1))
90 else if (the_count
== long (ACE_MAX_TIMERS
- 1))
95 else if (current_count
== -1)
97 int result
= ACE_Reactor::instance ()->reset_timer_interval (this->timer_id (),
98 std::chrono::seconds
{the_count
+ 1});
100 ACE_ERROR ((LM_ERROR
,
101 ACE_TEXT ("Error resetting timer interval\n")));
103 the_count
+= (1 + odd
);
108 Time_Handler::timer_id () const
110 return this->timer_id_
;
114 Time_Handler::timer_id (long t
)
120 test_registering_all_handlers ()
122 ACE_Trace
t (ACE_TEXT ("test_registering_all_handler"),
124 ACE_TEXT_CHAR_TO_TCHAR (__FILE__
));
125 Time_Handler rt
[ACE_MAX_TIMERS
];
126 long t_id
[ACE_MAX_TIMERS
];
128 for (size_t i
= 0; i
< ACE_MAX_TIMERS
; i
++)
131 ACE_Reactor::instance ()->schedule_timer (&rt
[i
],
133 std::chrono::seconds
{2 * i
+ 1});
134 ACE_TEST_ASSERT (t_id
[i
] != -1);
135 rt
[i
].timer_id (t_id
[i
]);
139 ACE_Reactor::instance ()->handle_events ();
143 test_registering_one_handler ()
145 ACE_Trace
t (ACE_TEXT ("test_registering_one_handler"),
147 ACE_TEXT_CHAR_TO_TCHAR (__FILE__
));
148 Time_Handler rt
[ACE_MAX_TIMERS
];
149 long t_id
[ACE_MAX_TIMERS
];
154 for (size_t i
= 0; i
< ACE_MAX_TIMERS
; i
++)
157 ACE_Reactor::instance ()->schedule_timer (&rt
[0],
159 ACE_Time_Value (2 * i
+ 1));
160 ACE_TEST_ASSERT (t_id
[i
] != -1);
164 ACE_Reactor::instance ()->handle_events ();
168 test_canceling_odd_timers ()
170 ACE_Trace
t (ACE_TEXT ("test_canceling_odd_timers"),
172 ACE_TEXT_CHAR_TO_TCHAR (__FILE__
));
173 Time_Handler rt
[ACE_MAX_TIMERS
];
174 long t_id
[ACE_MAX_TIMERS
];
180 for (size_t i
= 0; i
< ACE_MAX_TIMERS
; i
++)
182 t_id
[i
] = ACE_Reactor::instance ()->schedule_timer (&rt
[i
],
184 ACE_Time_Value (2 * i
+ 1));
185 ACE_TEST_ASSERT (t_id
[i
] != -1);
186 rt
[i
].timer_id (t_id
[i
]);
189 for (size_t j
= 0; (u_long
) j
< ACE_MAX_TIMERS
; j
++)
190 // Cancel handlers with odd numbered timer ids.
191 if (ACE_ODD (rt
[j
].timer_id ()))
194 ACE_Reactor::instance ()->cancel_timer (rt
[j
].timer_id ());
196 ACE_ERROR ((LM_ERROR
,
197 ACE_TEXT ("Error cancelling timer\n")));
201 ACE_Reactor::instance ()->handle_events ();
205 test_resetting_timer_intervals ()
207 ACE_Trace
t (ACE_TEXT ("test_resetting_timer_intervals"),
209 ACE_TEXT_CHAR_TO_TCHAR (__FILE__
));
218 ACE_Reactor::instance ()->schedule_timer
222 // Start off by making this an interval timer.
225 ACE_TEST_ASSERT (t_id
!= -1);
229 ACE_Reactor::instance ()->handle_events ();
232 // If any command line arg is given, run the test with high res timer
233 // queue. Else run it normally.
235 run_main (int argc
, ACE_TCHAR
*[])
237 ACE_START_TEST (ACE_TEXT ("Reactor_Timer_Test"));
241 ACE_DEBUG ((LM_DEBUG
,
242 ACE_TEXT ("Running with high-res timer queue\n")));
243 ACE_Reactor
*r
= ACE_Reactor::instance ();
245 (void) ACE_High_Res_Timer::global_scale_factor ();
247 // Change the source of time in the Reactor to the
248 // high-resolution timer. Why does this test require such
249 // precision for a 1 second timer is beyond me ... I think it
250 // is a cut&paste error.
252 // The use of auto_ptr<> is optional, ACE uses dangerous memory
253 // management idioms everywhere, I thought I could demonstrate how
254 // to do it right in at least one test. Notice the lack of
255 // ACE_NEW_RETURN, that monstrosity has no business in proper C++
257 std::unique_ptr
<ACE_Timer_Heap_Variable_Time_Source
> tq(
258 new ACE_Timer_Heap_Variable_Time_Source
);
259 // ... notice how the policy is in the derived timer queue type.
260 // The abstract timer queue does not have a time policy ...
261 tq
->set_time_policy(&ACE_High_Res_Timer::gettimeofday_hr
);
262 // ... and then the timer queue is replaced. Strangely, the
263 // Reactor does *not* copy the timers, it just deletes the
264 // existing timer queue ....
265 r
->timer_queue(tq
.get());
266 // ... the Reactor has assumed ownership, release the
271 // Register all different handlers, i.e., one per timer.
272 test_registering_all_handlers ();
274 // Now try multiple timers for ONE event handler (should produce the
276 test_registering_one_handler ();
278 // Try canceling handlers with odd numbered timer ids.
279 test_canceling_odd_timers ();
281 // Make sure <reset_timer_inverval> works.
282 test_resetting_timer_intervals ();