Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / ACE / tests / Recursive_Mutex_Test.cpp
blob4ecd657ffa28666da6d820636f1ed73b1d295477
2 //=============================================================================
3 /**
4 * @file Recursive_Mutex_Test.cpp
6 * This test program verifies the functionality of the ACE_OS
7 * implementation of recursive mutexes on Win32 and Posix
8 * pthreads.
10 * @author Prashant Jain <pjain@cs.wustl.edu> and Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
12 //=============================================================================
15 #include "test_config.h"
16 #include "ace/Get_Opt.h"
17 #include "ace/Thread_Manager.h"
18 #include "ace/OS_NS_time.h"
19 #include "ace/OS_NS_sys_time.h"
20 #include "ace/OS_NS_unistd.h"
21 #include "ace/Recursive_Thread_Mutex.h"
24 #if defined (ACE_HAS_THREADS)
26 #include "ace/Guard_T.h"
28 // For all platforms except for Windows use the
29 // ACE_Recursive_Thread_Mutex. Since Windows only supports timed
30 // recursive process mutexes and not timed recursive thread mutexes,
31 // use ACE_Process_Mutex.
32 #if defined (ACE_HAS_WTHREADS)
33 # include "ace/Process_Mutex.h"
34 typedef ACE_Process_Mutex ACE_TEST_MUTEX;
35 #else
36 # include "ace/Thread_Mutex.h"
37 using ACE_TEST_MUTEX = ACE_Recursive_Thread_Mutex;
38 #endif
40 #if !defined (ACE_HAS_MUTEX_TIMEOUTS)
41 static int reported_notsup = 0;
42 #endif /* ACE_HAS_MUTEX_TIMEOUTS */
44 // Total number of iterations.
45 static int const n_iterations = 100;
46 static size_t n_threads = ACE_MAX_THREADS;
48 // ACE_Recursive_Thread_Mutex::get_nesting_level() will return a
49 // meaningful value.
50 #if !defined (ACE_HAS_WTHREADS)
51 static bool nesting_level_supported = false;
52 #endif
54 static void
55 test_recursion_depth (int nesting_level,
56 ACE_TEST_MUTEX *rm)
58 if (nesting_level < n_iterations)
60 #if !defined (ACE_HAS_WTHREADS)
61 // This will work for Windows, too, if ACE_TEST_MUTEX is
62 // ACE_Recursive_Thread_Mutex instead of ACE_Process_Mutex.
63 if (nesting_level_supported
64 && nesting_level != 0
65 && nesting_level != rm->get_nesting_level ())
67 ACE_ERROR ((LM_ERROR,
68 ACE_TEXT ("(%P|%t) Pre-mutex acquire nesting ")
69 ACE_TEXT ("levels do not match.\n")));
71 #endif /* !ACE_HAS_WTHREADS */
72 int result = rm->acquire ();
73 ACE_TEST_ASSERT (result == 0);
74 #if !defined (ACE_HAS_WTHREADS)
75 if (nesting_level_supported
76 && (nesting_level + 1) != rm->get_nesting_level ())
78 ACE_ERROR ((LM_ERROR,
79 ACE_TEXT ("(%P|%t) Post-mutex acquire nesting ")
80 ACE_TEXT ("levels do not match.\n")));
83 ACE_DEBUG ((LM_DEBUG,
84 ACE_TEXT ("(%P|%t) = acquired, nesting = %d, thread id = %u\n"),
85 rm->get_nesting_level (),
86 rm->get_thread_id ()));
87 #endif /* !ACE_HAS_WTHREADS */
89 test_recursion_depth (nesting_level + 1,
90 rm);
92 #if !defined (ACE_HAS_WTHREADS)
93 if (nesting_level_supported
94 && (nesting_level + 1) != rm->get_nesting_level ())
96 ACE_ERROR ((LM_ERROR,
97 ACE_TEXT ("(%P|%t) Post recursion nesting ")
98 ACE_TEXT ("levels do not match.\n")));
100 #endif /* !ACE_HAS_WTHREADS */
101 result = rm->release ();
102 ACE_TEST_ASSERT (result == 0);
103 #if !defined (ACE_HAS_WTHREADS)
104 ACE_DEBUG ((LM_DEBUG,
105 ACE_TEXT ("(%P|%t) = released, nesting = %d, thread id = %u\n"),
106 rm->get_nesting_level (),
107 rm->get_thread_id ()));
109 if (nesting_level_supported
110 && nesting_level != 0
111 && nesting_level != rm->get_nesting_level ())
113 ACE_ERROR ((LM_ERROR,
114 ACE_TEXT ("(%P|%t) Post-mutex release nesting ")
115 ACE_TEXT ("levels do not match.\n")));
117 #endif /* !ACE_HAS_WTHREADS */
121 static void
122 test_timed_wait (int nesting_level,
123 ACE_TEST_MUTEX *rm)
125 // Make sure that we're inside of a recursive level.
126 if (nesting_level == 0)
127 test_timed_wait (nesting_level + 1,
128 rm);
129 else
131 u_int seed = (u_int) ACE_OS::time (0);
133 for (size_t i = 0; i < ACE_MAX_ITERATIONS / 2; i++)
135 int result = 0;
137 // First attempt to acquire the mutex with a timeout to verify
138 // that mutex timeouts are working.
140 ACE_DEBUG ((LM_DEBUG,
141 ACE_TEXT ("(%P|%t) = trying timed acquire on ")
142 ACE_TEXT ("iteration %d\n"),
143 i));
145 ACE_Time_Value delta (1, 0); // One second timeout
146 ACE_Time_Value timeout = ACE_OS::gettimeofday ();
147 timeout += delta; // Must pass absolute time to acquire().
149 if (rm->acquire (timeout) != 0)
151 if (errno == ETIME)
152 ACE_DEBUG ((LM_DEBUG,
153 ACE_TEXT ("(%P|%t) = mutex acquisition ")
154 ACE_TEXT ("timed out\n")));
155 else if (errno == ENOTSUP)
157 #if !defined (ACE_HAS_MUTEX_TIMEOUTS)
158 if (!reported_notsup)
160 ACE_DEBUG ((LM_INFO,
161 ACE_TEXT ("(%P|%t) %p, but ACE_HAS_MUTEX_TIMEOUTS is not defined - Ok\n"),
162 ACE_TEXT ("mutex timed acquire")));
163 reported_notsup = 1;
165 #else
166 ACE_DEBUG ((LM_ERROR,
167 ACE_TEXT ("(%P|%t) %p - maybe ACE_HAS_MUTEX_TIMEOUTS should not be defined?\n"),
168 ACE_TEXT ("mutex timed acquire")));
169 #endif /* ACE_HAS_MUTEX_TIMEOUTS */
171 else
173 ACE_ERROR ((LM_ERROR,
174 ACE_TEXT ("(%P|%t) %p\n%a"),
175 ACE_TEXT ("mutex timeout failed\n")));
176 return;
179 else
181 result = rm->release ();
182 ACE_TEST_ASSERT (result == 0);
185 // Now try the standard mutex.
187 ACE_DEBUG ((LM_DEBUG,
188 ACE_TEXT ("(%P|%t) = trying to acquire on iteration %d\n"),
189 i));
190 result = rm->acquire ();
191 ACE_TEST_ASSERT (result == 0);
192 ACE_DEBUG ((LM_DEBUG,
193 ACE_TEXT ("(%P|%t) = acquired on iteration %d\n"),
194 i));
196 // Sleep for a random amount of time between 0 and 2 seconds.
197 // Note that it's ok to use rand() here because we are running
198 // within the critical section defined by the Thread_Mutex.
199 ACE_OS::sleep (ACE_OS::rand_r (&seed) % 2);
201 result = rm->release ();
202 ACE_TEST_ASSERT (result == 0);
203 ACE_DEBUG ((LM_DEBUG,
204 ACE_TEXT ("(%P|%t) = released on iteration %d\n"),
205 i));
207 // FUZZ: disable check_for_ACE_Guard
208 // Basic ACE_Guard usage - automatically acquire the mutex on
209 // guard construction and automatically release it on
210 // destruction.
212 // Construct an ACE_Guard to implicitly acquire the mutex.
213 ACE_Guard<ACE_TEST_MUTEX> guard (*rm);
214 ACE_TEST_ASSERT (guard.locked () != 0);
216 // Perform some operation which might exit the current scope
217 // prematurely, e.g. by returning or throwing an exception.
218 // ...
220 // ACE_Guard object is destroyed when exiting scope and guard
221 // destructor automatically releases mutex.
224 // Use an ACE_Guard to automatically acquire a mutex, but release
225 // the mutex early.
227 // Construct an ACE_Guard to implicitly acquire the mutex.
228 ACE_Guard<ACE_TEST_MUTEX> guard (*rm);
229 ACE_TEST_ASSERT (guard.locked () != 0);
231 // Perform some operation which might exit the current scope
232 // prematurely, e.g. by returning or throwing an exception.
233 // ...
235 // Release the mutex since we no longer need it.
236 guard.release ();
237 ACE_TEST_ASSERT (guard.locked () == 0);
239 // Do something else which does not require the mutex to be locked.
240 // ...
242 // ACE_Guard object's destructor will not release the mutex.
245 // Use an ACE_Guard to automatically acquire a mutex, but
246 // relinquish ownership of the lock so that the mutex is not
247 // automatically released on guard destruction. This is useful
248 // when an operation might not release the mutex in some
249 // conditions, in which case responsibility for releasing it is
250 // passed to someone else.
252 // Construct an ACE_Guard to implicitly acquire the mutex.
253 ACE_Guard<ACE_TEST_MUTEX> guard (*rm);
254 ACE_TEST_ASSERT (guard.locked () != 0);
256 // Perform some operation which might exit the current scope
257 // prematurely, e.g. by returning or throwing an exception.
258 // ...
260 // Relinquish ownership of the mutex lock. Someone else must
261 // now release it.
262 guard.disown ();
263 ACE_TEST_ASSERT (guard.locked () == 0);
265 // ACE_Guard object's destructor will not release the mutex.
267 // We are now responsible for releasing the mutex.
268 result = rm->release ();
269 ACE_TEST_ASSERT (result == 0);
271 // Construct an ACE_Guard without automatically acquiring the lock.
273 // Construct an ACE_Guard object without automatically
274 // acquiring the mutex or taking ownership of an existing
275 // lock. The third parameter tells the guard that the mutex
276 // has not been locked.
277 ACE_Guard<ACE_TEST_MUTEX> guard (*rm, 0, 0);
278 ACE_TEST_ASSERT (guard.locked () == 0);
280 // Conditionally acquire the mutex.
281 if (i % 2 == 0)
283 guard.acquire ();
284 ACE_TEST_ASSERT (guard.locked () != 0);
287 // Perform some operation that might exit the current scope
288 // prematurely, e.g. by returning or throwing an exception.
289 // ...
291 // ACE_Guard object is destroyed when exiting scope and guard
292 // destructor automatically releases if it was acquired above.
295 // Use an ACE_Guard to take ownership of a previously acquired
296 // mutex.
297 timeout = ACE_OS::gettimeofday ();
298 timeout += delta; // Must pass absolute time to acquire().
299 if (rm->acquire (timeout) == 0)
301 // Construct an ACE_Guard object without automatically
302 // acquiring the mutex, but instead take ownership of the
303 // existing lock. The third parameter tells the guard that
304 // the mutex has already been locked.
305 ACE_Guard<ACE_TEST_MUTEX> guard (*rm, 0, 1);
306 ACE_TEST_ASSERT (guard.locked () != 0);
308 // Perform some operation which might exit the current scope
309 // prematurely, e.g. by returning or throwing an exception.
310 // ...
312 // ACE_Guard object is destroyed when exiting scope and guard
313 // destructor automatically releases mutex.
315 // FUZZ: enable check_for_ACE_Guard
318 return;
322 static void *
323 recursion_worker (void *arg)
325 ACE_TEST_MUTEX *rm =
326 reinterpret_cast<ACE_TEST_MUTEX *> (arg);
328 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%P|%t) Starting test of recursion depth\n")));
329 test_recursion_depth (0, rm);
331 return 0;
334 static void *
335 timed_worker (void *arg)
337 ACE_TEST_MUTEX *rm =
338 reinterpret_cast<ACE_TEST_MUTEX *> (arg);
340 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%P|%t) Starting test of timed wait\n")));
341 test_timed_wait (0, rm);
343 return 0;
346 #endif /* ACE_HAS_THREADS */
349 run_main (int argc, ACE_TCHAR *argv[])
351 ACE_START_TEST (ACE_TEXT ("Recursive_Mutex_Test"));
353 #if defined (ACE_HAS_THREADS)
354 if (argc > 1)
356 n_threads = ACE_OS::atoi (argv[1]);
359 ACE_TEST_MUTEX rm;
361 #if !defined (ACE_HAS_WTHREADS)
362 // This will work for Windows, too, if ACE_TEST_MUTEX is
363 // ACE_Recursive_Thread_Mutex instead of ACE_Process_Mutex.
364 nesting_level_supported =
365 (rm.get_nesting_level () != -1 || errno != ENOTSUP);
366 #endif /* !ACE_HAS_WTHREADS */
368 ACE_Thread_Manager::instance ()->spawn_n (n_threads,
369 ACE_THR_FUNC (recursion_worker),
370 (void *) &rm);
371 ACE_Thread_Manager::instance ()->wait ();
373 ACE_Thread_Manager::instance ()->spawn_n (n_threads,
374 ACE_THR_FUNC (timed_worker),
375 (void *) &rm);
376 ACE_Thread_Manager::instance ()->wait ();
377 #else
378 ACE_UNUSED_ARG (argc);
379 ACE_UNUSED_ARG (argv);
380 ACE_ERROR ((LM_ERROR,
381 ACE_TEXT ("ACE doesn't support recursive process ")
382 ACE_TEXT ("mutexes on this platform\n")));
383 #endif /* ACE_HAS_THREADS */
384 ACE_END_TEST;
385 return 0;