Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / ACE / tests / Recursive_Condition_Test.cpp
blobb7b30248c4bcbe72f320e7dcb856b0dbbf8a6254
2 //=============================================================================
3 /**
4 * @file Recursive_Condition_Test.cpp
6 * This test program validates the functionality of the
7 * ACE_Condition<ACE_Recursive_Thread_Mutex> template
8 * specialization.
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
29 public:
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);
45 ACE_DEBUG ((LM_DEBUG,
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")));
51 return 0;
54 private:
55 int nr_expirations_;
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
62 // waiter.
63 int protected_int = 0;
65 static ACE_THR_FUNC_RETURN
66 waiter (void *)
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")));
75 else
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
79 if (copy_int != 0)
80 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%t) waiter found protected_int %d\n"),
81 copy_int));
83 if (mutex_.release () != 0)
84 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("release")));
86 return 0;
89 static int
90 test_1 ()
92 protected_int = 1;
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")),
96 1);
98 ACE_OS::sleep (2);
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")));
105 protected_int = 0;
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 ();
115 return 0;
118 static int
119 test_2 ()
121 protected_int = 1;
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")),
127 ACE_OS::sleep (2);
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.
138 ACE_OS::sleep(2);
139 protected_int = 0;
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 ();
145 return 0;
148 static int
149 test_3 ()
151 protected_int = 1;
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);
156 ACE_OS::sleep (2);
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")));
166 protected_int = 0;
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 ();
173 return 0;
176 static int
177 test_4 ()
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);
186 ACE_OS::sleep (2);
187 int i;
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"),
191 i + 1,
192 ACE_TEXT ("recursive acquire")),
195 // Don't report a failure if the mutex doesn't offer a view of the
196 // recursion count.
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"),
201 nesting_level, i),
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.
214 --protected_int;
215 mutex_.release ();
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"),
227 nesting_level),
230 return 0;
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)
240 int status = 0;
242 /* Test 1 - Simple test */
243 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Test 1...\n")));
244 if (test_1 () != 0)
245 ++status;
247 /* Test #2 - Sleep 2 seconds before releasing mutex */
248 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Test 2...\n")));
249 if (test_2 () != 0)
250 ++status;
252 /* Test #3 - One main thread - 4 subthreads */
253 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Test 3...\n")));
254 if (test_3 () != 0)
255 ++status;
257 /* Test #4 - Multiple calls to mutex_.acquire and mutex_.release */
258 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Test 4...\n")));
259 if (test_4 () != 0)
260 ++status;
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")));
268 ++status;
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")));
277 ++status;
280 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Starting to sleep\n")));
281 ACE_OS::sleep (10);
282 timer_queue.deactivate ();
283 timer_queue.wait ();
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"),
287 expirations));
288 if (expirations < 9)
289 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Should have caught at least 9\n")));
291 #else
292 ACE_ERROR ((LM_ERROR,
293 ACE_TEXT ("ACE doesn't support recursive condition variables on this platform\n")));
294 #endif /* ACE_HAS_THREADS */
295 ACE_END_TEST;
296 return 0;