Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / tests / Monotonic_Task_Test.cpp
blob4e86cc27175c64b1b39e081f7c172e0d43ec26d2
2 //=============================================================================
3 /**
4 * @file Monotonic_Task_Test.cpp
6 * This is a test that verifies the time policy features of the
7 * ACE_Task template.
8 * A template instantiation based on the ACE_Monotonic_Time_Policy
9 * is used to demonstrate the ability for making the task message queue
10 * timeouts independent from system time changes (time shift).
11 * Also demonstrated is how to instantiate a thread manager which is time
12 * shift independent (for its wait timeouts) using time policy support for
13 * conditions.
15 * @author Martin Corino <mcorino@remedy.nl>
17 //=============================================================================
20 #include "test_config.h"
21 #include "ace/Reactor.h"
22 #include "ace/Timer_Queue.h"
23 #include "ace/Thread_Manager.h"
24 #include "ace/Message_Queue.h"
25 #include "ace/Monotonic_Time_Policy.h"
26 #include "ace/Synch_Traits.h"
27 #include "ace/Timer_Heap_T.h"
28 #include "ace/Event_Handler_Handle_Timeout_Upcall.h"
29 #include "ace/TP_Reactor.h"
30 #include "ace/Task_T.h"
31 #include "ace/Truncate.h"
32 #include "ace/OS_NS_stdio.h"
33 #include "ace/OS_NS_string.h"
34 #include "ace/OS_NS_sys_time.h"
35 #include "ace/OS_NS_time.h"
36 #include "ace/OS_NS_unistd.h"
38 #if defined (ACE_HAS_MONOTONIC_TIME_POLICY) && defined (ACE_HAS_MONOTONIC_CONDITIONS)
40 # if defined (ACE_WIN32)
41 # include "ace/Date_Time.h"
42 # endif
44 # if defined (ACE_HAS_THREADS)
46 void set_system_time(const ACE_Time_Value& tv)
48 # if defined (ACE_WIN32)
49 ACE_Date_Time curdt (tv);
50 SYSTEMTIME sys_time;
51 sys_time.wDay = ACE_Utils::truncate_cast <WORD> (curdt.day ());
52 sys_time.wMonth = ACE_Utils::truncate_cast <WORD> (curdt.month ());
53 sys_time.wYear = ACE_Utils::truncate_cast <WORD> (curdt.year ());
54 sys_time.wHour = ACE_Utils::truncate_cast <WORD> (curdt.hour ());
55 sys_time.wMinute = ACE_Utils::truncate_cast <WORD> (curdt.minute ());
56 sys_time.wSecond = ACE_Utils::truncate_cast <WORD> (curdt.second ());
57 sys_time.wMilliseconds = ACE_Utils::truncate_cast <WORD> (curdt.microsec () / 1000);
58 if (!::SetLocalTime (&sys_time))
59 # else
60 timespec_t curts;
61 curts = tv;
62 if (ACE_OS::clock_settime (CLOCK_REALTIME, &curts) != 0)
63 # endif
65 ACE_DEBUG((LM_INFO,
66 "(%P|%t) Unable to reset OS time. Insufficient privileges or not supported.\n"));
70 class MyTask : public ACE_Task<ACE_MT_SYNCH, ACE_Monotonic_Time_Policy>
72 public:
73 MyTask ()
74 : stop_ (false),
75 tm_ (monotonic_cond_attr_),
76 cond_ (lock_, monotonic_cond_attr_),
77 status_ (0)
79 // set monotonic timer aware thread manager for this task
80 this->thr_mgr (&this->tm_);
83 ~MyTask () override { stop (); }
85 int svc () override;
87 int start ();
89 int put_message ();
91 int stop ();
93 int status () { return this->status_; }
95 private:
96 bool stop_;
97 ACE_Condition_Attributes_T<ACE_Monotonic_Time_Policy> monotonic_cond_attr_;
98 ACE_Thread_Manager tm_;
99 ACE_Thread_Mutex lock_;
100 ACE_Condition<ACE_Thread_Mutex> cond_;
101 int status_;
105 MyTask::start ()
107 ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%P|%t) Starting MyTask\n")));
109 ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
111 if (this->activate (THR_NEW_LWP, 1) == -1)
112 ACE_ERROR_RETURN ((LM_ERROR,
113 ACE_TEXT ("%p.\n"),
114 ACE_TEXT ("unable to activate thread")),
115 -1);
117 if (this->cond_.wait () != 0) // wait for task to start
119 ACE_ERROR_RETURN ((LM_ERROR,
120 ACE_TEXT ("Failed waiting for thread")),
121 -1);
124 return 0;
128 MyTask::put_message ()
130 const char S1[] = "message";
132 ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
134 // Now (according to task time policy = monotonic time)
135 ACE_Time_Value_T<ACE_Monotonic_Time_Policy> tv (this->gettimeofday ());
136 tv += ACE_Time_Value (5,0); // Now + 5 sec
138 // wait for signal; should not come causing us to sleep 5 sec (monotonic)
139 if (this->cond_.wait (&tv) == 0)
141 ACE_ERROR_RETURN ((LM_ERROR,
142 ACE_TEXT ("(%P|%t) MyTask::put_message - Received signal from thread before timeout\n")),
143 -1);
146 ACE_DEBUG ((LM_DEBUG, "(%P|%t) MyTask::put_message - queueing message\n"));
148 ACE_Message_Block* mb1 = new ACE_Message_Block(S1, sizeof S1);
150 if (this->putq (mb1) < 0)
152 ACE_ERROR_RETURN ((LM_ERROR,
153 ACE_TEXT ("(%P|%t) MyTask::put_message - Failed to queue message\n")),
154 -1);
157 return 0;
161 MyTask::stop ()
163 ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%P|%t) Stopping MyTask\n")));
166 ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
168 this->stop_ = true;
170 if (this->cond_.signal () != 0)
172 ACE_ERROR_RETURN ((LM_ERROR,
173 ACE_TEXT ("Failed signalling thread\n")),
174 -1);
178 return this->wait ();
182 MyTask::svc ()
184 ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%P|%t) MyTask::svc started\n")));
186 // Now (according to task time policy = monotonic time)
187 ACE_Time_Value_T<ACE_Monotonic_Time_Policy> tv (this->gettimeofday ());
190 ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
192 ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%P|%t) MyTask::svc - signalling waiter\n")));
194 this->cond_.signal (); // signal waiter we have started
195 // waiter will shift system time back 4 sec after this which would mess
196 // up the first wait for a message if we were not using monotonic time
199 if (!this->msg_queue ()->is_empty ())
201 ACE_ERROR ((LM_ERROR,
202 ACE_TEXT ("New task queue is not empty!\n")));
203 this->status_ = -1;
205 else
207 ACE_Message_Block *b;
208 tv += ACE_Time_Value (3,0); // Now + 3 sec
210 if (this->getq (b, &tv) != -1)
212 ACE_ERROR ((LM_ERROR,
213 ACE_TEXT ("Dequeued before timeout elapsed!\n")));
214 this->status_ = -1;
216 else if (errno != EWOULDBLOCK)
218 ACE_ERROR ((LM_ERROR,
219 ACE_TEXT ("%p\n"),
220 ACE_TEXT ("Dequeue timeout should be EWOULDBLOCK, got")));
221 this->status_ = -1;
223 else
225 ACE_Time_Value_T<ACE_Monotonic_Time_Policy> tv_now (this->gettimeofday ());
227 ACE_DEBUG ((LM_DEBUG,
228 ACE_TEXT ("First getq timed out at %#T (timeout was %#T)\n"), &tv_now, &tv));
230 tv = this->gettimeofday () + ACE_Time_Value (4,0); // Now (monotonic time) + 3 sec
231 if (this->getq (b, &tv) != -1)
233 tv_now = tv.now ();
235 ACE_DEBUG ((LM_DEBUG,
236 ACE_TEXT ("Second getq succeeded at %#T\n"), &tv_now));
237 delete b;
239 else
241 ACE_ERROR ((LM_ERROR,
242 ACE_TEXT ("Second getq timed out!\n")));
243 this->status_ = -1;
249 ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
251 ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%P|%t) MyTask::svc - waiting for stop\n")));
253 if (!this->stop_)
254 this->cond_.wait ();
257 ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%t) MyTask finished\n")));
258 return 0;
261 # endif /* ACE_HAS_THREADS */
264 run_main (int , ACE_TCHAR *[])
266 ACE_START_TEST (ACE_TEXT ("Monotonic_Task_Test"));
268 int status = 0;
270 # if defined (ACE_HAS_THREADS)
271 MyTask my_task;
273 if (my_task.start () == 0)
275 // shift back in time 4 sec; this would mess up timeouts if
276 // monotonic timer was not used
277 ACE_Time_Value tv_shift (4, 0);
278 set_system_time (ACE_OS::gettimeofday () - tv_shift);
280 if (my_task.put_message () == 0)
282 // task should now have finished dequeueing and started waiting for stop signal
283 // wait (2sec) on thread manager should timeout
285 // use the time policy aware gettimeofday()
286 // method of the task to get current time
287 ACE_Time_Value_T<ACE_Monotonic_Time_Policy> tv (my_task.gettimeofday ());
288 tv += ACE_Time_Value (2, 0);
290 // shift another 3 sec back in time; without monotonic timer support in
291 // thread manager this would mess up the timed wait
292 tv_shift += ACE_Time_Value (3, 0);
293 set_system_time (ACE_OS::gettimeofday () - ACE_Time_Value (3,0));
295 if (my_task.thr_mgr ()->wait (&tv) == 0)
297 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Thread manager did not time out\n")));
298 status = 1;
300 else
302 ACE_Time_Value_T<ACE_Monotonic_Time_Policy> tv_now (my_task.gettimeofday ());
304 ACE_DEBUG ((LM_INFO, ACE_TEXT ("Thread manager timed out at %#T\n"), &tv_now));
307 else
308 status = 1;
310 // ok, now stop task
311 if (my_task.stop () != 0)
313 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Failed to stop task\n")));
314 status = 1;
317 // restore time
318 set_system_time (ACE_OS::gettimeofday () + tv_shift);
320 else
321 status = 1;
323 # endif /* ACE_HAS_THREADS */
325 ACE_END_TEST;
326 return status;
329 #else
332 run_main (int , ACE_TCHAR *[])
334 ACE_START_TEST (ACE_TEXT ("Monotonic_Task_Test"));
335 ACE_DEBUG((LM_INFO,
336 "(%P|%t) ACE not compiled with monotonic time.\n"));
337 ACE_END_TEST;
338 return 0;
341 #endif