1 //=============================================================================
3 * @file Bug_4055_Regression_Test.cpp
5 * @author Johnny Willemsen (jwillemsen@remedy.nl)
7 //=============================================================================
9 #include "test_config.h"
10 #include "ace/Reactor.h"
11 #include "ace/Timer_Queue.h"
12 #include "ace/Time_Value_T.h"
13 #include "ace/Monotonic_Time_Policy.h"
14 #include "ace/Condition_Thread_Mutex.h"
15 #include "ace/Condition_Attributes.h"
16 #include "ace/OS_NS_sys_time.h"
17 #include "ace/High_Res_Timer.h"
18 #include "ace/Get_Opt.h"
19 #include "ace/Timer_Heap_T.h"
20 #include "ace/Event_Handler_Handle_Timeout_Upcall.h"
21 #include "ace/TP_Reactor.h"
22 #include "ace/Task_T.h"
23 #include "ace/Truncate.h"
25 #if defined (ACE_HAS_MONOTONIC_TIME_POLICY) && defined (ACE_HAS_MONOTONIC_CONDITIONS)
27 # if defined (ACE_HAS_THREADS)
29 # if defined (ACE_WIN32)
30 # include "ace/Date_Time.h"
33 // Create timer queue with hr support
35 create_timer_queue (void)
37 ACE_Timer_Queue
* tmq
= 0;
39 typedef ACE_Timer_Heap_T
<ACE_Event_Handler
*,
40 ACE_Event_Handler_Handle_Timeout_Upcall
,
41 ACE_SYNCH_RECURSIVE_MUTEX
,
42 ACE_HR_Time_Policy
> timer_queue_type
;
43 ACE_NEW_RETURN (tmq
, timer_queue_type (), 0);
48 class MyTask
: public ACE_Task
<ACE_MT_SYNCH
>
51 MyTask () : my_reactor_ (0), my_tq_ (0) {}
53 virtual ~MyTask () { stop (); }
55 virtual int svc (void);
57 int start (int num_threads
);
59 ACE_Reactor
* get_reactor ();
60 int create_reactor (void);
63 int delete_reactor (void);
65 ACE_SYNCH_RECURSIVE_MUTEX lock_
;
66 ACE_Reactor
*my_reactor_
;
67 ACE_Timer_Queue
*my_tq_
;
71 MyTask::get_reactor ()
77 MyTask::create_reactor (void)
79 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
,
84 ACE_TEST_ASSERT (this->my_reactor_
== 0);
86 this->my_tq_
= create_timer_queue ();
88 ACE_TP_Reactor
* pImpl
= 0;
89 ACE_NEW_RETURN (pImpl
,ACE_TP_Reactor (0, this->my_tq_
), -1);
91 ACE_NEW_RETURN (my_reactor_
,
92 ACE_Reactor (pImpl
,1),
96 ACE_TEXT (" (%t) Create TP_Reactor\n")));
98 this->reactor (my_reactor_
);
104 MyTask::delete_reactor (void)
106 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX
,
111 ACE_DEBUG ((LM_DEBUG
,
112 ACE_TEXT (" (%t) Delete TP_Reactor\n")));
115 delete this->my_reactor_
;
116 this->my_reactor_
= 0;
123 MyTask::start (int num_threads
)
125 if (this->activate (THR_NEW_LWP
, num_threads
) == -1)
126 ACE_ERROR_RETURN ((LM_ERROR
,
128 ACE_TEXT ("unable to activate thread pool")),
138 if (this->my_reactor_
!= 0)
140 ACE_DEBUG ((LM_DEBUG
,
141 ACE_TEXT ("End TP_Reactor event loop\n")));
143 this->my_reactor_
->end_reactor_event_loop ();
146 if (this->wait () == -1)
147 ACE_ERROR ((LM_ERROR
,
149 ACE_TEXT ("unable to stop thread pool")));
151 if (this->delete_reactor () == -1)
152 ACE_ERROR ((LM_ERROR
,
154 ACE_TEXT ("unable to delete reactor")));
162 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT (" (%P|%t) MyTask started\n")));
164 while (this->my_reactor_
->reactor_event_loop_done () == 0)
165 this->my_reactor_
->run_reactor_event_loop ();
167 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT (" (%t) MyTask finished\n")));
172 : public ACE_Event_Handler
175 TestHandler (ACE_Reactor
* reactor
)
176 : reactor_ (reactor
),
177 timeout_triggered_ (false)
180 virtual int handle_timeout (const ACE_Time_Value
&tv
,
183 bool trigger_in(const ACE_Time_Value
&delay
);
185 bool timeout_triggered () { return this->timeout_triggered_
; }
188 ACE_Reactor
* reactor_
;
189 bool timeout_triggered_
;
192 int TestHandler::handle_timeout (const ACE_Time_Value
&,
195 ACE_DEBUG ((LM_DEBUG
, "(%P|%t) TestHandler::handle_timeout - timeout triggered\n"));
196 this->timeout_triggered_
= true;
200 bool TestHandler::trigger_in(const ACE_Time_Value
&delay
)
202 ACE_DEBUG ((LM_DEBUG
, "(%P|%t) TestHandler::trigger_in - scheduling timer\n"));
203 return -1 != reactor_
->schedule_timer (this, 0, delay
, ACE_Time_Value (0));
206 bool test_timer (ACE_Condition_Thread_Mutex
& condition_
, ACE_Time_Value
& waittime
, bool monotonic
= false)
210 task1
.create_reactor ();
212 TestHandler
test_handler (task1
.get_reactor ());
214 // The second reactor that uses a hrtimer will trigger a timeout in
215 // 5 seconds. At the same moment we calculate a timeout for the condition
216 // 3 seconds in the future. Than we set the time 4 seconds back.
217 // at the moment now the condition timeouts the trigger should have not
218 // been executed. This is because with hrtime the trigger will call in 5
219 // seconds and the condition in 3 seconds, independent of any time change
220 // meaning that the timeout should trigger
221 if (!test_handler
.trigger_in (ACE_Time_Value (5, 0)))
222 ACE_ERROR_RETURN ((LM_ERROR
,
223 "(%P|%t) Unable to schedule trigger.\n"),
226 waittime
+= ACE_Time_Value (3,0);
228 // reset system clock 4 seconds backwards
229 ACE_Time_Value curtime
= ACE_OS::gettimeofday ();
230 curtime
-= ACE_Time_Value (4, 0);
231 # if defined (ACE_WIN32)
232 ACE_Date_Time
curdt (curtime
);
234 sys_time
.wDay
= ACE_Utils::truncate_cast
<WORD
> (curdt
.day ());
235 sys_time
.wMonth
= ACE_Utils::truncate_cast
<WORD
> (curdt
.month ());
236 sys_time
.wYear
= ACE_Utils::truncate_cast
<WORD
> (curdt
.year ());
237 sys_time
.wHour
= ACE_Utils::truncate_cast
<WORD
> (curdt
.hour ());
238 sys_time
.wMinute
= ACE_Utils::truncate_cast
<WORD
> (curdt
.minute ());
239 sys_time
.wSecond
= ACE_Utils::truncate_cast
<WORD
> (curdt
.second ());
240 sys_time
.wMilliseconds
= ACE_Utils::truncate_cast
<WORD
> (curdt
.microsec () / 1000);
241 if (!::SetLocalTime (&sys_time
))
245 if (ACE_OS::clock_settime (CLOCK_REALTIME
, &curts
) != 0)
249 "(%P|%t) Unable to reset OS time. Insufficient privileges or not supported.\n"));
254 "(%P|%t) Going to wait on condition until %#T.\n", &waittime
));
255 if (condition_
.wait (&waittime
) != -1 || errno
!= ETIME
)
257 ACE_ERROR ((LM_ERROR
, "ERROR: No errno or return -1\n"));
261 "(%P|%t) Condition wait returned at %#T.\n", &waittime
));
263 if (test_handler
.timeout_triggered ())
267 ACE_ERROR ((LM_ERROR
, "(%P|%t) ERROR: timer handler shouldn't have "
268 "triggered because we used monotonic condition timing!\n"));
272 ACE_DEBUG ((LM_INFO
, "(%P|%t) timer handler "
273 "triggered because we used non-monotonic condition timing!\n"));
279 ACE_ERROR ((LM_ERROR
, "(%P|%t) ERROR: timer handler should have "
280 "triggered because we used non-monotonic condition timing!\n"));
284 ACE_DEBUG ((LM_INFO
, "(%P|%t) timer handler has not "
285 "triggered because we used monotonic condition timing!\n"));
288 // reset system clock to correct time
289 curtime
= ACE_OS::gettimeofday ();
290 curtime
+= ACE_Time_Value (4, 0);
291 # if defined (ACE_WIN32)
292 curdt
.update (curtime
);
294 sys_time
.wDay
= ACE_Utils::truncate_cast
<WORD
> (curdt
.day ());
295 sys_time
.wMonth
= ACE_Utils::truncate_cast
<WORD
> (curdt
.month ());
296 sys_time
.wYear
= ACE_Utils::truncate_cast
<WORD
> (curdt
.year ());
297 sys_time
.wHour
= ACE_Utils::truncate_cast
<WORD
> (curdt
.hour ());
298 sys_time
.wMinute
= ACE_Utils::truncate_cast
<WORD
> (curdt
.minute ());
299 sys_time
.wSecond
= ACE_Utils::truncate_cast
<WORD
> (curdt
.second ());
300 sys_time
.wMilliseconds
= ACE_Utils::truncate_cast
<WORD
> (curdt
.microsec () / 1000);
301 if (!::SetLocalTime (&sys_time
))
304 if (ACE_OS::clock_settime (CLOCK_REALTIME
, &curts
) != 0)
308 "(%P|%t) Unable to reset OS time. Insufficient privileges or not supported.\n"));
313 "(%P|%t) Asking worker thread to finish.\n"));
316 ACE_Thread_Manager::instance ()->wait ();
323 run_main (int , ACE_TCHAR
*[])
325 ACE_START_TEST (ACE_TEXT ("Bug_4055_Regression_Test"));
326 # if defined (ACE_HAS_THREADS)
329 ACE_Thread_Mutex mutex_
;
330 ACE_Condition_Thread_Mutex
condition_ (mutex_
);
331 ACE_Condition_Attributes_T
<ACE_Monotonic_Time_Policy
> monotonic_cond_attr_
;
332 ACE_Condition_Thread_Mutex
monotonic_condition_ (mutex_
, monotonic_cond_attr_
);
334 if (mutex_
.acquire () != 0)
336 ACE_ERROR ((LM_ERROR
, "(%P|%t) ERROR: Failed to acquire mutex.\n"));
340 ACE_Time_Value waittime
;
341 waittime
= waittime
.now ();
342 if (test_timer (condition_
, waittime
))
344 ACE_Time_Value_T
<ACE_Monotonic_Time_Policy
> monotonic_waittime
;
345 monotonic_waittime
= monotonic_waittime
.now ();
346 if (test_timer (monotonic_condition_
, monotonic_waittime
, true))
360 run_main (int , ACE_TCHAR
*[])
362 ACE_START_TEST (ACE_TEXT ("Bug_4055_Regression_Test"));
364 "(%P|%t) ACE not compiled with monotonic time.\n"));