ACE+TAO-7_0_8
[ACE_TAO.git] / ACE / tests / Timer_Queue_Reference_Counting_Test.cpp
blob94f7f395e85f7f9cffbdfa639c1d6766e2137ac7
2 //=============================================================================
3 /**
4 * @file Timer_Queue_Reference_Counting_Test.cpp
6 * This test is used to check reference counting of the Event
7 * Handler when it interacts with Timer Queues.
9 * @author Irfan Pyarali <irfan@oomworks.com>
11 //=============================================================================
14 #include "test_config.h"
15 #include "ace/Get_Opt.h"
16 #include "ace/Timer_Queue.h"
17 #include "ace/Timer_Heap.h"
18 #include "ace/Timer_List.h"
19 #include "ace/Timer_Hash.h"
20 #include "ace/Timer_Wheel.h"
21 #include "ace/Reactor.h"
22 #include "ace/Recursive_Thread_Mutex.h"
23 #include "ace/Null_Mutex.h"
24 #include "ace/OS_NS_unistd.h"
28 static int debug = 0;
29 static const char *one_second_timeout = "one second timeout";
30 static const char *two_second_timeout = "two second timeout";
32 namespace
34 inline void WAIT_FOR_NEXT_EVENT (ACE_Timer_Queue &timer_queue)
36 ACE_Time_Value const earliest_time = timer_queue.earliest_time ();
37 ACE_Time_Value const time_of_day = timer_queue.gettimeofday ();
38 if (earliest_time > time_of_day)
40 ACE_OS::sleep (earliest_time - time_of_day);
45 class Reference_Counted_Event_Handler : public ACE_Event_Handler
47 public:
49 Reference_Counted_Event_Handler (int expected_number_of_handle_close_calls);
51 ~Reference_Counted_Event_Handler () override;
53 int handle_timeout (const ACE_Time_Value &,
54 const void *) override;
56 int handle_close (ACE_HANDLE handle,
57 ACE_Reactor_Mask masks) override;
59 int expected_number_of_handle_close_calls_;
60 int number_of_handle_close_calls_;
63 Reference_Counted_Event_Handler::Reference_Counted_Event_Handler (int expected_number_of_handle_close_calls)
64 : expected_number_of_handle_close_calls_ (expected_number_of_handle_close_calls),
65 number_of_handle_close_calls_ (0)
67 this->reference_counting_policy ().value
68 (ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
70 if (debug)
71 ACE_DEBUG ((LM_DEBUG,
72 "Reference count in Reference_Counted_Event_Handler() is %d\n",
73 this->reference_count_.load ()));
76 Reference_Counted_Event_Handler::~Reference_Counted_Event_Handler ()
78 if (debug)
79 ACE_DEBUG ((LM_DEBUG,
80 "Reference count in ~Reference_Counted_Event_Handler() is %d\n",
81 this->reference_count_.load ()));
83 if (this->expected_number_of_handle_close_calls_ != -1)
84 ACE_TEST_ASSERT (this->number_of_handle_close_calls_ ==
85 this->expected_number_of_handle_close_calls_);
88 int
89 Reference_Counted_Event_Handler::handle_timeout (const ACE_Time_Value &,
90 const void *arg)
92 if (debug)
93 ACE_DEBUG ((LM_DEBUG,
94 "Reference count in Reference_Counted_Event_Handler::handle_timeout() for arg = %C is %d\n",
95 (const char *) arg,
96 this->reference_count_.load ()));
98 return 0;
102 Reference_Counted_Event_Handler::handle_close (ACE_HANDLE handle,
103 ACE_Reactor_Mask masks)
105 if (debug)
106 ACE_DEBUG ((LM_DEBUG,
107 "Reference_Counted_Event_Handler::handle_close() called with handle = %d and masks = %d. "
108 "Reference count is %d\n",
109 handle,
110 masks,
111 this->reference_count_.load ()));
113 ++this->number_of_handle_close_calls_;
115 return 0;
118 void
119 cancellation (ACE_Timer_Queue &timer_queue,
120 int repeat_timer,
121 int cancel_handler,
122 int second_timer,
123 int dont_call_handle_close)
125 int result = 0;
127 int expected_number_of_handle_close_calls = -1;
129 if (!dont_call_handle_close)
131 if (cancel_handler)
132 expected_number_of_handle_close_calls = 1;
133 else if (second_timer)
134 expected_number_of_handle_close_calls = 2;
135 else
136 expected_number_of_handle_close_calls = 1;
139 Reference_Counted_Event_Handler *handler =
140 new Reference_Counted_Event_Handler (expected_number_of_handle_close_calls);
142 ACE_Event_Handler_var safe_handler (handler);
144 long first_timer_id = -1;
145 long second_timer_id = -1;
147 if (repeat_timer)
149 first_timer_id =
150 timer_queue.schedule (handler,
151 one_second_timeout,
152 ACE_Time_Value (1) + timer_queue.gettimeofday (),
153 ACE_Time_Value (1));
154 ACE_TEST_ASSERT (first_timer_id != -1);
156 else
158 first_timer_id =
159 timer_queue.schedule (handler,
160 one_second_timeout,
161 ACE_Time_Value (1) + timer_queue.gettimeofday ());
162 ACE_TEST_ASSERT (first_timer_id != -1);
165 if (second_timer)
167 second_timer_id =
168 timer_queue.schedule (handler,
169 two_second_timeout,
170 ACE_Time_Value (2) + timer_queue.gettimeofday (),
171 ACE_Time_Value (2));
172 ACE_TEST_ASSERT (second_timer_id != -1);
175 if (cancel_handler)
177 result =
178 timer_queue.cancel (handler,
179 dont_call_handle_close);
181 if (second_timer)
182 ACE_TEST_ASSERT (result == 2);
183 else
184 ACE_TEST_ASSERT (result == 1);
186 else
188 result =
189 timer_queue.cancel (first_timer_id,
191 dont_call_handle_close);
192 ACE_TEST_ASSERT (result == 1);
194 if (second_timer)
196 result =
197 timer_queue.cancel (second_timer_id,
199 dont_call_handle_close);
200 ACE_TEST_ASSERT (result == 1);
205 template <class TIMER_QUEUE>
206 class cancellation_test
208 public:
209 cancellation_test (const char *);
212 template <class TIMER_QUEUE>
213 cancellation_test<TIMER_QUEUE>::cancellation_test (const char *timer_queue_type)
215 ACE_DEBUG ((LM_DEBUG,
216 "\nCancellation test for %C\n\n",
217 timer_queue_type));
219 int configs[][4] = {
220 { 0, 0, 0, 0, },
221 { 0, 0, 0, 1, },
222 { 0, 0, 1, 0, },
223 { 0, 0, 1, 1, },
224 { 0, 1, 0, 0, },
225 { 0, 1, 0, 1, },
226 { 0, 1, 1, 0, },
227 { 0, 1, 1, 1, },
228 { 1, 0, 0, 0, },
229 { 1, 0, 0, 1, },
230 { 1, 0, 1, 0, },
231 { 1, 0, 1, 1, },
232 { 1, 1, 0, 0, },
233 { 1, 1, 0, 1, },
234 { 1, 1, 1, 0, },
235 { 1, 1, 1, 1, },
238 for (int i = 0;
239 i < (int) (sizeof configs / (sizeof (int) * 5));
240 i++)
242 TIMER_QUEUE timer_queue;
244 cancellation (timer_queue,
245 configs[i][0],
246 configs[i][1],
247 configs[i][2],
248 configs[i][3]);
252 using Expire_Function = int (*)(ACE_Timer_Queue &);
255 invoke_expire (ACE_Timer_Queue &timer_queue)
257 return timer_queue.expire ();
261 invoke_one_upcall (ACE_Timer_Queue &timer_queue)
263 ACE_Noop_Command command;
264 return timer_queue.expire_single(command);
267 void
268 expire (ACE_Timer_Queue &timer_queue,
269 Expire_Function expire_function)
271 int events = 0;
272 int result = 0;
274 Reference_Counted_Event_Handler *handler =
275 new Reference_Counted_Event_Handler (1);
277 ACE_Event_Handler_var safe_handler (handler);
279 long timer_id =
280 timer_queue.schedule (handler,
281 one_second_timeout,
282 ACE_Time_Value (1) + timer_queue.gettimeofday (),
283 ACE_Time_Value (1));
284 ACE_TEST_ASSERT (timer_id != -1);
286 result =
287 timer_queue.schedule (handler,
288 two_second_timeout,
289 ACE_Time_Value (2) + timer_queue.gettimeofday ());
290 ACE_TEST_ASSERT (result != -1);
292 events += 4;
294 for (int i = 0; i < events;)
296 WAIT_FOR_NEXT_EVENT (timer_queue);
298 result =
299 expire_function (timer_queue);
301 ACE_TEST_ASSERT (result >= 0);
303 i += result;
306 timer_queue.cancel (timer_id, 0, 0);
309 template<class TIMER_QUEUE>
310 class expire_test
312 public:
313 expire_test (const char *);
316 template <class TIMER_QUEUE>
317 expire_test<TIMER_QUEUE>::expire_test (const char *timer_queue_type)
319 ACE_DEBUG ((LM_DEBUG,
320 "\nExpire test for %C\n\n",
321 timer_queue_type));
323 TIMER_QUEUE timer_queue;
325 expire (timer_queue,
326 invoke_expire);
329 template<class TIMER_QUEUE>
330 class upcall_test
332 public:
333 upcall_test (const char *);
336 template <class TIMER_QUEUE>
337 upcall_test<TIMER_QUEUE>::upcall_test (const char *timer_queue_type)
339 ACE_DEBUG ((LM_DEBUG,
340 "\nOne upcall test for %C\n\n",
341 timer_queue_type));
343 TIMER_QUEUE timer_queue;
345 expire (timer_queue,
346 invoke_one_upcall);
349 class Simple_Event_Handler : public ACE_Event_Handler
351 public:
353 Simple_Event_Handler ();
355 ~Simple_Event_Handler () override;
357 int handle_timeout (const ACE_Time_Value &,
358 const void *) override;
360 int handle_close (ACE_HANDLE,
361 ACE_Reactor_Mask) override;
364 Simple_Event_Handler::Simple_Event_Handler ()
366 if (debug)
367 ACE_DEBUG ((LM_DEBUG,
368 "Simple_Event_Handler()\n"));
371 Simple_Event_Handler::~Simple_Event_Handler ()
373 if (debug)
374 ACE_DEBUG ((LM_DEBUG,
375 "~Simple_Event_Handler()\n"));
379 Simple_Event_Handler::handle_timeout (const ACE_Time_Value &,
380 const void *arg)
382 if (debug)
383 ACE_DEBUG ((LM_DEBUG,
384 "Simple_Event_Handler::handle_timeout() for arg = %C\n",
385 (const char *) arg));
386 return 0;
390 Simple_Event_Handler::handle_close (ACE_HANDLE handle,
391 ACE_Reactor_Mask masks)
393 if (debug)
394 ACE_DEBUG ((LM_DEBUG,
395 "Simple_Event_Handler::handle_close() called with handle = %d and masks = %d.\n",
396 handle,
397 masks));
399 delete this;
401 return 0;
404 void
405 simple (ACE_Timer_Queue &timer_queue)
407 int events = 0;
408 int result = 0;
409 long timer_id = -1;
412 Simple_Event_Handler *handler =
413 new Simple_Event_Handler;
415 timer_id =
416 timer_queue.schedule (handler,
417 one_second_timeout,
418 ACE_Time_Value (1) + timer_queue.gettimeofday (),
419 ACE_Time_Value (1));
420 ACE_TEST_ASSERT (timer_id != -1);
422 result =
423 timer_queue.cancel (timer_id,
426 ACE_TEST_ASSERT (result == 1);
430 Simple_Event_Handler *handler =
431 new Simple_Event_Handler;
433 timer_id =
434 timer_queue.schedule (handler,
435 one_second_timeout,
436 ACE_Time_Value (1) + timer_queue.gettimeofday (),
437 ACE_Time_Value (1));
438 ACE_TEST_ASSERT (timer_id != -1);
440 events += 3;
443 for (int i = 0; i < events;)
445 WAIT_FOR_NEXT_EVENT (timer_queue);
447 result =
448 timer_queue.expire ();
450 ACE_TEST_ASSERT (result >= 0);
452 i += result;
455 timer_queue.cancel (timer_id, 0, 0);
458 template <class TIMER_QUEUE>
459 class simple_test
461 public:
462 simple_test (const char *);
465 template <class TIMER_QUEUE>
466 simple_test<TIMER_QUEUE>::simple_test (const char *timer_queue_type)
468 ACE_DEBUG ((LM_DEBUG,
469 "\nSimple test for %C\n\n",
470 timer_queue_type));
472 TIMER_QUEUE timer_queue;
474 simple (timer_queue);
477 static int heap = 1;
478 static int list = 1;
479 static int hash = 1;
480 static int wheel = 1;
481 static int hashheap = 1;
482 static int test_cancellation = 1;
483 static int test_expire = 1;
484 static int test_one_upcall = 1;
485 static int test_simple = 1;
487 static int
488 parse_args (int argc, ACE_TCHAR *argv[])
490 ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("a:b:c:d:e:l:m:n:o:z:"));
492 int cc;
493 while ((cc = get_opt ()) != -1)
495 switch (cc)
497 case 'a':
498 heap = ACE_OS::atoi (get_opt.opt_arg ());
499 break;
500 case 'b':
501 list = ACE_OS::atoi (get_opt.opt_arg ());
502 break;
503 case 'c':
504 hash = ACE_OS::atoi (get_opt.opt_arg ());
505 break;
506 case 'd':
507 wheel = ACE_OS::atoi (get_opt.opt_arg ());
508 break;
509 case 'e':
510 hashheap = ACE_OS::atoi (get_opt.opt_arg ());
511 break;
512 case 'l':
513 test_cancellation = ACE_OS::atoi (get_opt.opt_arg ());
514 break;
515 case 'm':
516 test_expire = ACE_OS::atoi (get_opt.opt_arg ());
517 break;
518 case 'n':
519 test_one_upcall = ACE_OS::atoi (get_opt.opt_arg ());
520 break;
521 case 'o':
522 test_simple = ACE_OS::atoi (get_opt.opt_arg ());
523 break;
524 case 'z':
525 debug = ACE_OS::atoi (get_opt.opt_arg ());
526 break;
527 default:
528 ACE_ERROR ((LM_ERROR,
529 ACE_TEXT ("\nusage: %s \n\n")
530 ACE_TEXT ("\t[-a heap] (defaults to %d)\n")
531 ACE_TEXT ("\t[-b list] (defaults to %d)\n")
532 ACE_TEXT ("\t[-c hash] (defaults to %d)\n")
533 ACE_TEXT ("\t[-d wheel] (defaults to %d)\n")
534 ACE_TEXT ("\t[-e hashheap] (defaults to %d)\n")
535 ACE_TEXT ("\t[-l test_cancellation] (defaults to %d)\n")
536 ACE_TEXT ("\t[-m test_expire] (defaults to %d)\n")
537 ACE_TEXT ("\t[-n test_one_upcall] (defaults to %d)\n")
538 ACE_TEXT ("\t[-o test_simple] (defaults to %d)\n")
539 ACE_TEXT ("\t[-z debug] (defaults to %d)\n")
540 ACE_TEXT ("\n"),
541 argv[0],
542 heap,
543 list,
544 hash,
545 wheel,
546 hashheap,
547 test_cancellation,
548 test_expire,
549 test_one_upcall,
550 test_simple,
551 debug));
552 return -1;
556 return 0;
560 run_main (int argc, ACE_TCHAR *argv[])
562 ACE_START_TEST (ACE_TEXT ("Timer_Queue_Reference_Counting_Test"));
564 // Validate options.
565 int result =
566 parse_args (argc, argv);
567 if (result != 0)
568 return result;
570 if (test_cancellation)
572 ACE_DEBUG ((LM_DEBUG,
573 "\nCancellation test...\n\n"));
575 if (heap) { cancellation_test<ACE_Timer_Heap> test ("ACE_Timer_Heap"); ACE_UNUSED_ARG (test); }
576 if (list) { cancellation_test<ACE_Timer_List> test ("ACE_Timer_List"); ACE_UNUSED_ARG (test); }
577 if (hash) { cancellation_test<ACE_Timer_Hash> test ("ACE_Timer_Hash"); ACE_UNUSED_ARG (test); }
578 if (wheel) { cancellation_test<ACE_Timer_Wheel> test ("ACE_Timer_Wheel"); ACE_UNUSED_ARG (test); }
579 if (hashheap) { cancellation_test<ACE_Timer_Hash_Heap> test ("ACE_Timer_Hash_Heap"); ACE_UNUSED_ARG (test); }
582 if (test_expire)
584 ACE_DEBUG ((LM_DEBUG,
585 "\nExpire test...\n\n"));
587 if (heap) { expire_test<ACE_Timer_Heap> test ("ACE_Timer_Heap"); ACE_UNUSED_ARG (test); }
588 if (list) { expire_test<ACE_Timer_List> test ("ACE_Timer_List"); ACE_UNUSED_ARG (test); }
589 if (hash) { expire_test<ACE_Timer_Hash> test ("ACE_Timer_Hash"); ACE_UNUSED_ARG (test); }
590 if (wheel) { expire_test<ACE_Timer_Wheel> test ("ACE_Timer_Wheel"); ACE_UNUSED_ARG (test); }
591 if (hashheap) { expire_test<ACE_Timer_Hash_Heap> test ("ACE_Timer_Hash_Heap"); ACE_UNUSED_ARG (test); }
594 if (test_one_upcall)
596 ACE_DEBUG ((LM_DEBUG,
597 "\nOne upcall at a time test...\n\n"));
599 if (heap) { upcall_test<ACE_Timer_Heap> test ("ACE_Timer_Heap"); ACE_UNUSED_ARG (test); }
600 if (list) { upcall_test<ACE_Timer_List> test ("ACE_Timer_List"); ACE_UNUSED_ARG (test); }
601 if (hash) { upcall_test<ACE_Timer_Hash> test ("ACE_Timer_Hash"); ACE_UNUSED_ARG (test); }
602 if (wheel) { upcall_test<ACE_Timer_Wheel> test ("ACE_Timer_Wheel"); ACE_UNUSED_ARG (test); }
603 if (hashheap) { upcall_test<ACE_Timer_Hash_Heap> test ("ACE_Timer_Hash_Heap"); ACE_UNUSED_ARG (test); }
606 if (test_simple)
608 ACE_DEBUG ((LM_DEBUG,
609 "\nSimple test...\n\n"));
611 if (heap) { simple_test<ACE_Timer_Heap> test ("ACE_Timer_Heap"); ACE_UNUSED_ARG (test); }
612 if (list) { simple_test<ACE_Timer_List> test ("ACE_Timer_List"); ACE_UNUSED_ARG (test); }
613 if (hash) { simple_test<ACE_Timer_Hash> test ("ACE_Timer_Hash"); ACE_UNUSED_ARG (test); }
614 if (wheel) { simple_test<ACE_Timer_Wheel> test ("ACE_Timer_Wheel"); ACE_UNUSED_ARG (test); }
615 if (hashheap) { simple_test<ACE_Timer_Hash_Heap> test ("ACE_Timer_Hash_Heap"); ACE_UNUSED_ARG (test); }
618 ACE_END_TEST;
620 return 0;