2 //=============================================================================
4 * @file Monotonic_Manual_Event_Test.cpp
6 * This test verifies the functionality of the time policy support
7 * for the <ACE_Manual_Event> implementation.
9 * @author Martin Corino <mcorino@remedy.nl>
11 //=============================================================================
14 #include "test_config.h"
15 #include "ace/Manual_Event.h"
16 #include "ace/Thread.h"
17 #include "ace/Thread_Manager.h"
18 #include "ace/Get_Opt.h"
19 #include "ace/OS_NS_sys_time.h"
20 #include "ace/OS_NS_time.h"
21 #include "ace/OS_NS_unistd.h"
22 #include "ace/Atomic_Op.h"
24 #if defined (ACE_HAS_MONOTONIC_TIME_POLICY) && defined (ACE_HAS_MONOTONIC_CONDITIONS)
25 # include "ace/Monotonic_Time_Policy.h"
26 # if defined (ACE_WIN32)
27 # include "ace/Date_Time.h"
28 # include "ace/Truncate.h"
31 // Test results, 'success' is 0
32 static int test_result
= 0;
34 # if defined (ACE_HAS_THREADS)
36 // Event used in the tests. Start it "unsignalled" (i.e., its initial
38 static ACE_Event_Base
*evt
= 0;
40 // use monotonic or system time policy
41 static bool use_monotonic
= true;
43 // Number of worker threads.
44 static long n_workers
= 10;
46 // Absolute timeout for initial wait of workers
47 static ACE_Time_Value
*initial_timeout
;
50 # if defined (ACE_HAS_BUILTIN_ATOMIC_OP)
51 static ACE_Atomic_Op
<ACE_Thread_Mutex
, long> n_awoken
;
52 static ACE_Atomic_Op
<ACE_Thread_Mutex
, long> n_awoken2
;
55 static long n_awoken2
;
58 // Explain usage and exit.
60 print_usage_and_die ()
63 ACE_TEXT ("usage: %n [-w n_workers] [-s]\n")));
68 parse_args (int argc
, ACE_TCHAR
*argv
[])
70 ACE_Get_Opt
get_opt (argc
, argv
, ACE_TEXT ("w:s"));
74 while ((c
= get_opt ()) != -1)
78 n_workers
= ACE_OS::atoi (get_opt
.opt_arg ());
81 use_monotonic
= false;
84 print_usage_and_die ();
89 void set_system_time(const ACE_Time_Value
& tv
)
91 # if defined (ACE_WIN32)
92 ACE_Date_Time
curdt (tv
);
94 sys_time
.wDay
= ACE_Utils::truncate_cast
<WORD
> (curdt
.day ());
95 sys_time
.wMonth
= ACE_Utils::truncate_cast
<WORD
> (curdt
.month ());
96 sys_time
.wYear
= ACE_Utils::truncate_cast
<WORD
> (curdt
.year ());
97 sys_time
.wHour
= ACE_Utils::truncate_cast
<WORD
> (curdt
.hour ());
98 sys_time
.wMinute
= ACE_Utils::truncate_cast
<WORD
> (curdt
.minute ());
99 sys_time
.wSecond
= ACE_Utils::truncate_cast
<WORD
> (curdt
.second ());
100 sys_time
.wMilliseconds
= ACE_Utils::truncate_cast
<WORD
> (curdt
.microsec () / 1000);
101 if (!::SetLocalTime (&sys_time
))
105 if (ACE_OS::clock_settime (CLOCK_REALTIME
, &curts
) != 0)
109 "(%P|%t) Unable to reset OS time. Insufficient privileges or not supported.\n"));
113 // Worker tries to acquire the semaphore, hold it for a while, and
114 // then manually releases it.
119 if (evt
->wait (initial_timeout
) == -1)
121 if (ACE_OS::last_error () == ETIME
)
123 ACE_Time_Value tm_now
= initial_timeout
->now ();
124 ACE_ERROR_RETURN ((LM_ERROR
,
125 ACE_TEXT (" (%P|%t) Timed out waiting for start pulse at %#T\n"),
130 ACE_ERROR_RETURN ((LM_ERROR
,
131 ACE_TEXT (" (%P|%t) %p\n"),
132 ACE_TEXT ("Failed waiting for pulse ()")),
136 ACE_Time_Value tm_now
= initial_timeout
->now ();
137 ACE_DEBUG ((LM_DEBUG
,
138 ACE_TEXT (" (%P|%t) awake at %#T\n"), &tm_now
));
140 if (++n_awoken
< n_workers
)
143 ACE_Time_Value_T
<ACE_Monotonic_Time_Policy
> tm_mono
;
144 ACE_Time_Value tm_sys
;
146 //FUZZ: disable check_for_lack_ACE_OS
147 ACE_Time_Value
wait (1, 0); // Wait 1 sec
148 //FUZZ: enable check_for_lack_ACE_OS
152 tm_mono
= tm_mono
.now () + wait
;
157 tm_sys
= ACE_OS::gettimeofday () + wait
;
161 if (evt
->wait (tv
) == -1)
163 // verify that we have ETIME
164 if (ACE_OS::last_error () == ETIME
)
165 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT (" (%P|%t) timeout\n")));
167 ACE_ERROR ((LM_ERROR
,
168 ACE_TEXT (" (%P|%t) wait failed %p\n"),
169 ACE_TEXT ("but not with ETIME")));
173 ACE_DEBUG ((LM_DEBUG
,
174 ACE_TEXT (" (%P|%t) awake in time\n")));
176 if (++n_awoken2
>= (n_workers
/2))
177 evt
->reset (); // reset signal (rest times out)
180 // Check to ensure that an "infinite timeout" will work.
181 if (evt
->wait (0) == -1)
183 //FUZZ: disable check_for_lack_ACE_OS
184 ACE_ERROR ((LM_ERROR
,
185 ACE_TEXT (" (%P|%t) %p\n"),
186 ACE_TEXT ("Failed waiting for signal ()\n")));
187 //FUZZ: enable check_for_lack_ACE_OS
192 ACE_DEBUG ((LM_DEBUG
,
193 ACE_TEXT (" (%P|%t) last awake; send signal\n")));
194 // last one wakes others
195 if (evt
->signal () == -1)
196 ACE_ERROR ((LM_ERROR
, ACE_TEXT (" (%P|%t) %p\n"), ACE_TEXT ("signal")));
198 ACE_OS::sleep (ACE_Time_Value (0, 200 * 1000 * 100)); // 200 msec
201 if (evt
->wait () == -1)
203 //FUZZ: disable check_for_lack_ACE_OS
204 ACE_ERROR ((LM_ERROR
,
205 ACE_TEXT (" (%P|%t) %p\n"),
206 ACE_TEXT ("Failed waiting for signal ()\n")));
207 //FUZZ: enable check_for_lack_ACE_OS
210 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT (" (%P|%t) worker finished\n")));
215 # endif /* ACE_HAS_THREADS */
217 // Test event functionality.
219 int run_main (int argc
, ACE_TCHAR
*argv
[])
221 ACE_START_TEST (ACE_TEXT ("Monotonic_Manual_Event_Test"));
223 # if defined (ACE_HAS_THREADS)
224 ACE_Manual_Event_T
<ACE_Monotonic_Time_Policy
> monotonic_event (0);
225 ACE_Manual_Event
systime_event (0);
226 ACE_Time_Value_T
<ACE_Monotonic_Time_Policy
> tm_mono
;
227 ACE_Time_Value tm_sys
;
229 parse_args (argc
, argv
);
231 //FUZZ: disable check_for_lack_ACE_OS
232 ACE_Time_Value
wait (7, 0); // Wait 7 sec
233 //FUZZ: enable check_for_lack_ACE_OS
237 evt
= &monotonic_event
;
238 tm_mono
= tm_mono
.now () + wait
;
239 initial_timeout
= &tm_mono
;
243 evt
= &systime_event
;
244 tm_sys
= ACE_OS::gettimeofday () + wait
;
245 initial_timeout
= &tm_sys
;
248 // shift forward in time 3 sec; this will mess up timeouts if
249 // monotonic timer is not used
250 ACE_Time_Value
tv_shift (3, 0);
251 set_system_time (ACE_OS::gettimeofday () + tv_shift
);
253 ACE_DEBUG ((LM_DEBUG
,
254 ACE_TEXT ("spawning workers - initial timeout till %#T\n"), initial_timeout
));
256 if (ACE_Thread_Manager::instance ()->spawn_n
257 (static_cast<size_t> (n_workers
),
258 ACE_THR_FUNC (worker
),
261 ACE_ERROR_RETURN ((LM_ERROR
,
263 ACE_TEXT ("spawn_n")),
266 // gives all workers chance to start
269 ACE_DEBUG ((LM_DEBUG
,
270 ACE_TEXT ("finished waiting for workers to start\n")));
272 // restore time (workers will already have failed without monotonic timer)
273 set_system_time (ACE_OS::gettimeofday () - tv_shift
);
275 ACE_DEBUG ((LM_DEBUG
,
276 ACE_TEXT ("sending pulse ()\n")));
278 // Release the all workers.
279 if (evt
->pulse () == -1)
280 ACE_ERROR_RETURN ((LM_ERROR
,
288 //FUZZ: disable check_for_lack_ACE_OS
289 ACE_DEBUG ((LM_DEBUG
,
290 ACE_TEXT ("sending signal ()\n")));
291 //FUZZ: enable check_for_lack_ACE_OS
294 if (evt
->signal () == -1)
295 ACE_ERROR_RETURN ((LM_ERROR
,
297 ACE_TEXT ("signal")),
300 ACE_Thread_Manager::instance ()->wait ();
302 ACE_UNUSED_ARG (argc
);
303 ACE_UNUSED_ARG (argv
);
305 ACE_TEXT ("Threads not supported on this platform\n")));
306 # endif /* ACE_HAS_THREADS */
314 run_main (int , ACE_TCHAR
*[])
316 ACE_START_TEST (ACE_TEXT ("Monotonic_Manual_Event_Test"));
318 "(%P|%t) ACE not compiled with monotonic time.\n"));