2 //=============================================================================
4 * @file Recursive_Condition_Test.cpp
6 * This test program validates the functionality of the
7 * ACE_Condition<ACE_Recursive_Thread_Mutex> template
10 * @author Stephen Howard <stephen.e.howard@lmco.com> and Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
12 //=============================================================================
14 #include "test_config.h"
15 #include "ace/OS_NS_unistd.h"
16 #include "ace/OS_NS_sys_time.h"
17 #include "ace/Event_Handler.h"
18 #include "ace/Log_Msg.h"
19 #include "ace/Thread_Manager.h"
20 #include "ace/Timer_Heap.h"
21 #include "ace/Timer_Queue_Adapters.h"
23 #if defined (ACE_HAS_THREADS)
25 using Thread_Timer_Queue
= ACE_Thread_Timer_Queue_Adapter
<ACE_Timer_Heap
>;
27 class Test_Handler
: public ACE_Event_Handler
30 Test_Handler () : nr_expirations_ (0) {}
31 int nr_expirations () { return this->nr_expirations_
; }
33 int handle_timeout (const ACE_Time_Value
&,
34 const void *arg
) override
36 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) Test_Handler::handle_timeout\n")));
37 ++this->nr_expirations_
;
39 void *nc_arg
= const_cast<void *> (arg
);
40 Thread_Timer_Queue
*timer_queue
=
41 reinterpret_cast<Thread_Timer_Queue
*> (nc_arg
);
43 ACE_Time_Value timeout
= ACE_OS::gettimeofday () + ACE_Time_Value (1, 0);
46 ACE_TEXT ("(%t) scheduling new timer 1 sec from now\n")));
47 if (timer_queue
->schedule (this, timer_queue
, timeout
) == -1)
48 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
49 ACE_TEXT ("schedule failed")));
58 // These are for the basic functionality tests.
59 ACE_SYNCH_RECURSIVE_MUTEX mutex_
;
60 ACE_Condition
<ACE_SYNCH_RECURSIVE_MUTEX
> condition_ (mutex_
);
61 // Test driver sets this to non-zero before spawning and to zero for
63 int protected_int
= 0;
65 static ACE_THR_FUNC_RETURN
68 if (mutex_
.acquire () != 0)
69 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
70 ACE_TEXT ("acquire")), 0);
72 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) waiting for cv signal...\n")));
73 if (condition_
.wait () == 0)
74 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) woken up!!!\n")));
76 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("wait")));
78 int const copy_int
= protected_int
; // Copy it in case it's erroneously changing
80 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%t) waiter found protected_int %d\n"),
83 if (mutex_
.release () != 0)
84 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("release")));
93 if (ACE_Thread_Manager::instance()->spawn (waiter
) == -1)
94 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
95 ACE_TEXT ("test 1 spawn")),
99 if (mutex_
.acquire () == -1)
100 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
101 ACE_TEXT ("test 1 mutex acquire")),
104 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) signaling condition...\n")));
106 if (condition_
.signal () == -1)
107 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
108 ACE_TEXT ("test 1 signal")));
110 if (mutex_
.release () == -1)
111 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
112 ACE_TEXT ("test 1 release")));
114 ACE_Thread_Manager::instance ()->wait ();
122 if (ACE_Thread_Manager::instance()->spawn (waiter
) == -1)
123 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
124 ACE_TEXT ("test 2 spawn")),
128 if (mutex_
.acquire () == -1)
129 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
130 ACE_TEXT ("test 2 mutex acquire")),
132 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) signaling condition...\n")));
133 if (condition_
.signal () == -1)
134 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("%p\n"), ACE_TEXT ("test 2 signal")));
136 // Wait to clear protected_int to be sure cv properly reacquires the
137 // mutex before returning control to caller.
140 if (mutex_
.release () == -1)
141 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
142 ACE_TEXT ("test 2 release")));
144 ACE_Thread_Manager::instance ()->wait ();
152 if (ACE_Thread_Manager::instance()->spawn_n (4, waiter
) == -1)
153 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("%p\n"),
154 ACE_TEXT ("test 3 spawn")), 1);
157 if (mutex_
.acquire () == -1)
158 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
159 ACE_TEXT ("test 3 mutex acquire")),
162 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) broadcasting condition...\n")));
163 if (condition_
.broadcast () == -1)
164 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
165 ACE_TEXT ("test 3 broadcast")));
167 if (mutex_
.release () == -1)
168 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
169 ACE_TEXT ("test 3 release")));
171 ACE_Thread_Manager::instance ()->wait ();
179 const int recurse_count
= 3;
181 protected_int
= recurse_count
;
182 if (ACE_Thread_Manager::instance()->spawn (waiter
) == -1)
183 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
184 ACE_TEXT ("spawn")), 1);
188 for (i
= 0; i
< recurse_count
; ++i
)
189 if (mutex_
.acquire () == -1)
190 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("pass %d, %p\n"),
192 ACE_TEXT ("recursive acquire")),
195 // Don't report a failure if the mutex doesn't offer a view of the
197 int nesting_level
= mutex_
.get_nesting_level ();
198 if (!(nesting_level
== -1 && errno
== ENOTSUP
) && nesting_level
!= i
)
199 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT("test 4 nesting level %d;")
200 ACE_TEXT (" should be %d\n"),
204 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) signaling condition...\n")));
205 if (condition_
.signal () == -1)
206 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"),
207 ACE_TEXT ("test 4 signal")),
210 for (i
= 0; i
< recurse_count
; ++i
)
212 // Only decrement - be sure all the waiting threads are not released
213 // before we release the mutex the correct number of times.
218 // The waiter thread will acquire the mutex as a result of the releases
219 // above... don't check the nesting level until waiter() has had a chance
220 // to wake up, acquire, and release the mutex.
221 ACE_Thread_Manager::instance ()->wait ();
223 nesting_level
= mutex_
.get_nesting_level ();
224 if (!(nesting_level
== -1 && errno
== ENOTSUP
) && nesting_level
!= 0)
225 ACE_ERROR_RETURN ((LM_ERROR
,
226 ACE_TEXT("(%t) nesting level %d; should be 0\n"),
232 #endif /* ACE_HAS_THREADS */
235 run_main (int, ACE_TCHAR
*[])
237 ACE_START_TEST (ACE_TEXT ("Recursive_Condition_Test"));
239 #if defined (ACE_HAS_THREADS)
242 /* Test 1 - Simple test */
243 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Test 1...\n")));
247 /* Test #2 - Sleep 2 seconds before releasing mutex */
248 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Test 2...\n")));
252 /* Test #3 - One main thread - 4 subthreads */
253 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Test 3...\n")));
257 /* Test #4 - Multiple calls to mutex_.acquire and mutex_.release */
258 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Test 4...\n")));
262 // Timer queue usage.
263 Thread_Timer_Queue timer_queue
;
264 Test_Handler handler
;
265 if (0 != timer_queue
.activate ())
267 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("activate")));
271 ACE_Time_Value timeout
=
272 ACE_OS::gettimeofday() + ACE_Time_Value (1, 0);
274 if (-1 == timer_queue
.schedule (&handler
, &timer_queue
, timeout
))
276 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("schedule")));
280 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Starting to sleep\n")));
282 timer_queue
.deactivate ();
284 // Scheduling every second, waiting 10 seconds, should get at least 9
285 int expirations
= handler
.nr_expirations ();
286 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Caught %d timer expirations\n"),
289 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("Should have caught at least 9\n")));
292 ACE_ERROR ((LM_ERROR
,
293 ACE_TEXT ("ACE doesn't support recursive condition variables on this platform\n")));
294 #endif /* ACE_HAS_THREADS */