Use =default for skeleton copy constructor
[ACE_TAO.git] / ACE / tests / Bug_4055_Regression_Test.cpp
blob1e427befaeea941eb84cf5aa4af38fd0e44b1de5
1 //=============================================================================
2 /**
3 * @file Bug_4055_Regression_Test.cpp
5 * @author Johnny Willemsen (jwillemsen@remedy.nl)
6 */
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"
31 # endif
33 // Create timer queue with hr support
34 ACE_Timer_Queue *
35 create_timer_queue ()
37 ACE_Timer_Queue * tmq = 0;
39 using timer_queue_type = ACE_Timer_Heap_T<ACE_Event_Handler *, ACE_Event_Handler_Handle_Timeout_Upcall, ACE_MT_SYNCH::RECURSIVE_MUTEX, ACE_HR_Time_Policy>;
40 ACE_NEW_RETURN (tmq, timer_queue_type (), 0);
42 return tmq;
45 class MyTask : public ACE_Task<ACE_MT_SYNCH>
47 public:
48 MyTask () : my_reactor_ (0), my_tq_ (0) {}
50 ~MyTask () override { stop (); }
52 int svc () override;
54 int start (int num_threads);
55 int stop ();
56 ACE_Reactor* get_reactor ();
57 int create_reactor ();
59 private:
60 int delete_reactor ();
62 ACE_SYNCH_RECURSIVE_MUTEX lock_;
63 ACE_Reactor *my_reactor_;
64 ACE_Timer_Queue *my_tq_;
67 ACE_Reactor*
68 MyTask::get_reactor ()
70 return my_reactor_;
73 int
74 MyTask::create_reactor ()
76 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX,
77 monitor,
78 this->lock_,
79 -1);
81 ACE_TEST_ASSERT (this->my_reactor_ == 0);
83 this->my_tq_ = create_timer_queue ();
85 ACE_TP_Reactor * pImpl = 0;
86 ACE_NEW_RETURN (pImpl,ACE_TP_Reactor (0, this->my_tq_), -1);
88 ACE_NEW_RETURN (my_reactor_,
89 ACE_Reactor (pImpl ,1),
90 -1);
92 ACE_DEBUG ((LM_DEBUG,
93 ACE_TEXT (" (%t) Create TP_Reactor\n")));
95 this->reactor (my_reactor_);
97 return 0;
101 MyTask::delete_reactor ()
103 ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX,
104 monitor,
105 this->lock_,
106 -1);
108 ACE_DEBUG ((LM_DEBUG,
109 ACE_TEXT (" (%t) Delete TP_Reactor\n")));
111 this->reactor (0);
112 delete this->my_reactor_;
113 this->my_reactor_ = 0;
114 delete this->my_tq_;
115 this->my_tq_ = 0;
116 return 0;
120 MyTask::start (int num_threads)
122 if (this->activate (THR_NEW_LWP, num_threads) == -1)
123 ACE_ERROR_RETURN ((LM_ERROR,
124 ACE_TEXT ("%p.\n"),
125 ACE_TEXT ("unable to activate thread pool")),
126 -1);
128 return 0;
133 MyTask::stop ()
135 if (this->my_reactor_ != 0)
137 ACE_DEBUG ((LM_DEBUG,
138 ACE_TEXT ("End TP_Reactor event loop\n")));
140 this->my_reactor_->end_reactor_event_loop ();
143 if (this->wait () == -1)
144 ACE_ERROR ((LM_ERROR,
145 ACE_TEXT ("%p.\n"),
146 ACE_TEXT ("unable to stop thread pool")));
148 if (this->delete_reactor () == -1)
149 ACE_ERROR ((LM_ERROR,
150 ACE_TEXT ("%p.\n"),
151 ACE_TEXT ("unable to delete reactor")));
153 return 0;
157 MyTask::svc ()
159 ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%P|%t) MyTask started\n")));
161 while (this->my_reactor_->reactor_event_loop_done () == 0)
162 this->my_reactor_->run_reactor_event_loop ();
164 ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%t) MyTask finished\n")));
165 return 0;
168 class TestHandler
169 : public ACE_Event_Handler
171 public:
172 TestHandler (ACE_Reactor* reactor)
173 : reactor_ (reactor),
174 timeout_triggered_ (false)
177 int handle_timeout (const ACE_Time_Value &tv,
178 const void *arg) override;
180 bool trigger_in(const ACE_Time_Value &delay);
182 bool timeout_triggered () { return this->timeout_triggered_; }
184 private:
185 ACE_Reactor* reactor_;
186 bool timeout_triggered_;
189 int TestHandler::handle_timeout (const ACE_Time_Value &,
190 const void *)
192 ACE_DEBUG ((LM_DEBUG, "(%P|%t) TestHandler::handle_timeout - timeout triggered\n"));
193 this->timeout_triggered_ = true;
194 return 0;
197 bool TestHandler::trigger_in(const ACE_Time_Value &delay)
199 ACE_DEBUG ((LM_DEBUG, "(%P|%t) TestHandler::trigger_in - scheduling timer\n"));
200 return -1 != reactor_->schedule_timer (this, 0, delay, ACE_Time_Value (0));
203 bool test_timer (ACE_Condition_Thread_Mutex& condition_, ACE_Time_Value& waittime, bool monotonic = false)
205 bool status = true;
206 MyTask task1;
207 task1.create_reactor ();
208 task1.start (1);
209 TestHandler test_handler (task1.get_reactor ());
211 // The second reactor that uses a hrtimer will trigger a timeout in
212 // 5 seconds. At the same moment we calculate a timeout for the condition
213 // 3 seconds in the future. Than we set the time 4 seconds back.
214 // at the moment now the condition timeouts the trigger should have not
215 // been executed. This is because with hrtime the trigger will call in 5
216 // seconds and the condition in 3 seconds, independent of any time change
217 // meaning that the timeout should trigger
218 if (!test_handler.trigger_in (ACE_Time_Value (5, 0)))
219 ACE_ERROR_RETURN ((LM_ERROR,
220 "(%P|%t) Unable to schedule trigger.\n"),
221 false);
223 waittime += ACE_Time_Value (3,0);
225 // reset system clock 4 seconds backwards
226 ACE_Time_Value curtime = ACE_OS::gettimeofday ();
227 curtime -= ACE_Time_Value (4, 0);
228 # if defined (ACE_WIN32)
229 ACE_Date_Time curdt (curtime);
230 SYSTEMTIME sys_time;
231 sys_time.wDay = ACE_Utils::truncate_cast <WORD> (curdt.day ());
232 sys_time.wMonth = ACE_Utils::truncate_cast <WORD> (curdt.month ());
233 sys_time.wYear = ACE_Utils::truncate_cast <WORD> (curdt.year ());
234 sys_time.wHour = ACE_Utils::truncate_cast <WORD> (curdt.hour ());
235 sys_time.wMinute = ACE_Utils::truncate_cast <WORD> (curdt.minute ());
236 sys_time.wSecond = ACE_Utils::truncate_cast <WORD> (curdt.second ());
237 sys_time.wMilliseconds = ACE_Utils::truncate_cast <WORD> (curdt.microsec () / 1000);
238 if (!::SetLocalTime (&sys_time))
239 # else
240 timespec_t curts;
241 curts = curtime;
242 if (ACE_OS::clock_settime (CLOCK_REALTIME, &curts) != 0)
243 # endif
245 ACE_DEBUG((LM_INFO,
246 "(%P|%t) Unable to reset OS time. Insufficient privileges or not supported.\n"));
248 else
250 ACE_DEBUG((LM_INFO,
251 "(%P|%t) Going to wait on condition until %#T.\n", &waittime));
252 if (condition_.wait (&waittime) != -1 || errno != ETIME)
254 ACE_ERROR ((LM_ERROR, "ERROR: No errno or return -1\n"));
255 status = 1;
257 ACE_DEBUG((LM_INFO,
258 "(%P|%t) Condition wait returned at %#T.\n", &waittime));
260 if (test_handler.timeout_triggered ())
262 if (monotonic)
264 ACE_ERROR ((LM_ERROR, "(%P|%t) ERROR: timer handler shouldn't have "
265 "triggered because we used monotonic condition timing!\n"));
266 status = false;
268 else
269 ACE_DEBUG ((LM_INFO, "(%P|%t) timer handler "
270 "triggered because we used non-monotonic condition timing!\n"));
272 else
274 if (!monotonic)
276 ACE_ERROR ((LM_ERROR, "(%P|%t) ERROR: timer handler should have "
277 "triggered because we used non-monotonic condition timing!\n"));
278 status = false;
280 else
281 ACE_DEBUG ((LM_INFO, "(%P|%t) timer handler has not "
282 "triggered because we used monotonic condition timing!\n"));
285 // reset system clock to correct time
286 curtime = ACE_OS::gettimeofday ();
287 curtime += ACE_Time_Value (4, 0);
288 # if defined (ACE_WIN32)
289 curdt.update (curtime);
290 SYSTEMTIME sys_time;
291 sys_time.wDay = ACE_Utils::truncate_cast <WORD> (curdt.day ());
292 sys_time.wMonth = ACE_Utils::truncate_cast <WORD> (curdt.month ());
293 sys_time.wYear = ACE_Utils::truncate_cast <WORD> (curdt.year ());
294 sys_time.wHour = ACE_Utils::truncate_cast <WORD> (curdt.hour ());
295 sys_time.wMinute = ACE_Utils::truncate_cast <WORD> (curdt.minute ());
296 sys_time.wSecond = ACE_Utils::truncate_cast <WORD> (curdt.second ());
297 sys_time.wMilliseconds = ACE_Utils::truncate_cast <WORD> (curdt.microsec () / 1000);
298 if (!::SetLocalTime (&sys_time))
299 # else
300 curts = curtime;
301 if (ACE_OS::clock_settime (CLOCK_REALTIME, &curts) != 0)
302 # endif
304 ACE_DEBUG((LM_INFO,
305 "(%P|%t) Unable to reset OS time. Insufficient privileges or not supported.\n"));
309 ACE_DEBUG((LM_INFO,
310 "(%P|%t) Asking worker thread to finish.\n"));
311 task1.stop ();
313 ACE_Thread_Manager::instance ()->wait ();
315 return status;
317 # endif
320 run_main (int , ACE_TCHAR *[])
322 ACE_START_TEST (ACE_TEXT ("Bug_4055_Regression_Test"));
323 # if defined (ACE_HAS_THREADS)
324 int status = 1;
326 ACE_Thread_Mutex mutex_;
327 ACE_Condition_Thread_Mutex condition_ (mutex_);
328 ACE_Condition_Attributes_T<ACE_Monotonic_Time_Policy> monotonic_cond_attr_;
329 ACE_Condition_Thread_Mutex monotonic_condition_ (mutex_, monotonic_cond_attr_);
331 if (mutex_.acquire () != 0)
333 ACE_ERROR ((LM_ERROR, "(%P|%t) ERROR: Failed to acquire mutex.\n"));
335 else
337 ACE_Time_Value waittime;
338 waittime = waittime.now ();
339 if (test_timer (condition_, waittime))
341 ACE_Time_Value_T<ACE_Monotonic_Time_Policy> monotonic_waittime;
342 monotonic_waittime = monotonic_waittime.now ();
343 if (test_timer (monotonic_condition_, monotonic_waittime, true))
344 status = 0;
347 # else
348 int status = 0;
349 # endif
350 ACE_END_TEST;
351 return status;
354 #else
357 run_main (int , ACE_TCHAR *[])
359 ACE_START_TEST (ACE_TEXT ("Bug_4055_Regression_Test"));
360 ACE_DEBUG((LM_INFO,
361 "(%P|%t) ACE not compiled with monotonic time.\n"));
362 ACE_END_TEST;
363 return 0;
366 #endif