1 //=============================================================================
3 * @file Refcounted_Auto_Ptr_Test.cpp
5 * This example tests the <ACE_Refcounted_Auto_Ptr> and illustrates
6 * how they may be dispersed between multiple threads using an
7 * implementation of the Active Object pattern, which is available
8 * at <http://www.dre.vanderbilt.edu/~schmidt/PDF/Act-Obj.pdf>.
10 * @author Johnny Tucker <johnny_tucker@yahoo.com>
12 //=============================================================================
14 #include "test_config.h"
17 #include "ace/Message_Queue.h"
18 #include "ace/Method_Request.h"
19 #include "ace/Null_Mutex.h"
20 #include "ace/Activation_Queue.h"
21 #include "ace/Refcounted_Auto_Ptr.h"
22 #include "Refcounted_Auto_Ptr_Test.h"
24 ACE_Atomic_Op
<ACE_SYNCH_MUTEX
, unsigned int> Printer::current_instance_ (0);
25 ACE_Atomic_Op
<ACE_SYNCH_MUTEX
, long> Printer::instance_count_ (0);
27 Printer::Printer (const char *message
)
30 this->which_
= ++Printer::current_instance_
;
32 ACE_TEXT ("(%t) Creating Printer object %d (%C)\n"),
35 ++Printer::instance_count_
;
40 --Printer::instance_count_
;
42 ACE_TEXT ("(%t) Deleting Printer object %d (%C)\n"),
51 ACE_TEXT ("(%t) %C\n"),
55 #if defined (ACE_HAS_THREADS)
57 using Printer_var
= ACE_Refcounted_Auto_Ptr
<Printer
, ACE_Thread_Mutex
>;
62 * @brief The scheduler for the Active Object.
64 * This class also plays the role of the Proxy and the Servant
65 * in the Active Object pattern. Naturally, these roles could
66 * be split apart from the Scheduler.
68 class Scheduler
: public ACE_Task
<ACE_SYNCH
>
70 friend class Method_Request_print
;
71 friend class Method_Request_end
;
76 //FUZZ: disable check_for_lack_ACE_OS
78 int open (void *args
= 0) override
;
81 int close (u_long flags
= 0) override
;
82 //FUZZ: enable check_for_lack_ACE_OS
85 ~Scheduler () override
;
87 // = These methods are part of the Active Object Proxy interface.
88 void print (Printer_var
&printer
);
92 /// Runs the Scheduler's event loop, which dequeues <Method_Requests>
93 /// and dispatches them.
97 // = These are the <Scheduler> implementation details.
98 ACE_Activation_Queue activation_queue_
;
102 * @class Method_Request_print
104 * @brief Reification of the <print> method.
106 class Method_Request_print
: public ACE_Method_Request
109 explicit Method_Request_print (Printer_var
&printer
);
110 ~Method_Request_print () override
;
112 /// This is the entry point into the Active Object method.
113 int call () override
;
116 Printer_var printer_
;
119 Method_Request_print::Method_Request_print (Printer_var
&printer
)
122 ACE_DEBUG ((LM_DEBUG
,
123 ACE_TEXT ("(%t) Method_Request_print created\n")));
124 ACE_DEBUG ((LM_DEBUG
,
125 ACE_TEXT ("(%t) Printer reference count: %d\n"),
129 Method_Request_print::~Method_Request_print ()
131 ACE_DEBUG ((LM_DEBUG
,
132 ACE_TEXT ("(%t) Method_Request_print will be deleted.\n")));
133 ACE_DEBUG ((LM_DEBUG
,
134 ACE_TEXT ("(%t) Printer reference count: %d\n"),
139 Method_Request_print::call ()
141 // Dispatch the Servant's operation and store the result into the
143 Printer_var temp
= printer_
;
151 * @class Method_Request_end
153 * @brief Reification of the <end> method.
155 class Method_Request_end
: public ACE_Method_Request
158 Method_Request_end (Scheduler
*new_Prime_Scheduler
);
159 ~Method_Request_end () override
;
160 int call () override
;
163 Scheduler
*scheduler_
;
166 Method_Request_end::Method_Request_end (Scheduler
*scheduler
)
167 : scheduler_ (scheduler
)
171 Method_Request_end::~Method_Request_end ()
176 Method_Request_end::call ()
178 // Shut down the scheduler by deactivating the activation queue's
179 // underlying message queue - should pop all worker threads off their
180 // wait and they'll exit.
181 this->scheduler_
->msg_queue ()->deactivate ();
186 // Associates the activation queue with this task's message queue,
187 // allowing easy access to the message queue for shutting it down
188 // when it's time to stop this object's service threads.
189 Scheduler::Scheduler ()
190 : activation_queue_ (msg_queue ())
192 ACE_DEBUG ((LM_DEBUG
,
193 ACE_TEXT ("(%t) Scheduler created\n")));
198 Scheduler::~Scheduler ()
200 ACE_DEBUG ((LM_DEBUG
,
201 ACE_TEXT ("(%t) Scheduler will be destroyed\n")));
207 Scheduler::open (void *)
209 ACE_DEBUG ((LM_DEBUG
,
210 ACE_TEXT ("(%t) Scheduler open\n")));
211 // Become an Active Object.
213 return this->activate (THR_BOUND
| THR_JOINABLE
, num_threads
);
219 Scheduler::close (u_long
)
221 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) rundown\n")));
232 // Dequeue the next method request (we use an unique pointer in
233 // case an exception is thrown in the <call>).
234 ACE_Method_Request
*mo_p
= this->activation_queue_
.dequeue ();
237 ACE_DEBUG ((LM_DEBUG
,
238 ACE_TEXT ("(%t) activation queue shut down\n")));
241 std::unique_ptr
<ACE_Method_Request
> mo (mo_p
);
243 ACE_DEBUG ((LM_DEBUG
,
244 ACE_TEXT ("(%t) calling method request\n")));
246 if(mo
->call () == -1)
249 // Destructor automatically deletes it.
258 this->activation_queue_
.enqueue (new Method_Request_end (this));
261 // Here's where the work takes place.
264 Scheduler::print (Printer_var
&printer
)
266 this->activation_queue_
.enqueue
267 (new Method_Request_print (printer
));
270 // Total number of loops.
271 static int n_loops
= 10;
273 #endif /* ACE_HAS_THREADS */
276 // This will be used in a single thread to test the reset and release
277 // methods. See Bugzilla #1925 for history.
279 using Printer_Ptr
= ACE_Refcounted_Auto_Ptr
<Printer
, ACE_Null_Mutex
>;
281 static bool expect (const ACE_TCHAR
*name
,
282 const Printer_Ptr
&ptr
,
284 unsigned int expect_which
,
287 if (ptr
.null () != expect_null
)
290 ACE_DEBUG ((LM_DEBUG
,
291 ACE_TEXT ("Expecting: %s null:: ")
292 ACE_TEXT ("Actual: Printer: %u; Count %d\n"),
297 ACE_ERROR ((LM_ERROR
,
298 ACE_TEXT ("Expecting: %s Printer: %u; Count %d:: ")
299 ACE_TEXT ("Actual: Null.\n"),
307 ACE_DEBUG ((LM_DEBUG
,
308 ACE_TEXT ("Expecting: %s null:: Actual: Null.\n"),
313 // Note that count is zero based (0 means one reference, etc.)
314 bool fail
= (expect_which
!= ptr
->which_
) || (expect_count
!= ptr
.count ());
315 ACE_DEBUG ((fail
? LM_ERROR
: LM_DEBUG
,
316 ACE_TEXT ("Expecting: %s Printer: %u; Count %d:: ")
317 ACE_TEXT ("Actual: Printer: %u; Count %d\n"),
326 static int test_reset_release ()
330 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Test copy constructor\n")));
331 Printer_Ptr
bar(new Printer ("1"));
332 Printer_Ptr fum
= bar
;
333 if (!expect (ACE_TEXT ("bar"), bar
, false, 1, 1))
335 if (!expect (ACE_TEXT ("fum"), fum
, false, 1, 1))
338 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Test reset to a new value\n")));
339 bar
.reset (new Printer ("2"));
340 if (!expect (ACE_TEXT ("bar"), bar
, false, 2, 0))
342 if (!expect (ACE_TEXT ("fum"), fum
, false, 1, 0))
345 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Test release\n")));
346 Printer_Ptr
fie(new Printer ("3"));
347 Printer_Ptr foe
= fie
;
349 if (!expect (ACE_TEXT ("fie"), fie
, false, 3, 0))
351 if (!expect (ACE_TEXT ("foe"), foe
, true, 0, 0))
354 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Test assignment to null\n")));
355 Printer_Ptr
fee(new Printer ("4"));
358 if (!expect (ACE_TEXT ("fee"), fee
, true, 0, 0))
360 if (!expect (ACE_TEXT ("eraser"), eraser
, true, 0, 0))
363 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Test assignment to value\n")));
364 Printer_Ptr
fix(new Printer ("5"));
365 Printer_Ptr
fax(new Printer ("6"));
367 if (!expect (ACE_TEXT ("fix"), fix
, false, 6, 1))
369 if (!expect (ACE_TEXT ("fax"), fax
, false, 6, 1))
372 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("Test reset to null\n")));
373 Printer_Ptr
fey(new Printer ("7"));
374 Printer_Ptr flo
= fey
;
376 if (!expect (ACE_TEXT ("fey"), fey
, false, 7, 0))
378 if (!expect (ACE_TEXT ("flo"), flo
, true, 0, 0))
384 static int test_operator()
389 Printer_Ptr printer_null
;
396 ACE_ERROR ((LM_ERROR
,
397 ACE_TEXT ("!printer_null should be false\n")));
402 ACE_ERROR ((LM_ERROR
,
403 ACE_TEXT ("printer_null should be false\n")));
410 Printer_Ptr
printer_not_null(new Printer("check not null"));
411 if (!printer_not_null
)
414 ACE_ERROR ((LM_ERROR
,
415 ACE_TEXT ("!printer_not_null should be false\n")));
420 if (printer_not_null
)
426 ACE_ERROR ((LM_ERROR
,
427 ACE_TEXT ("printer_not_null should be false\n")));
434 run_main (int, ACE_TCHAR
*[])
436 ACE_START_TEST (ACE_TEXT ("Refcounted_Auto_Ptr_Test"));
440 // =========================================================================
441 // The following test uses the ACE_Refcounted_Auto_Ptr in a single
442 // thread of control, hence we use the ACE_Null_Mutex
444 ACE_DEBUG ((LM_DEBUG
,
445 ACE_TEXT ("(%t) performing synchronous tests...\n")));
447 test_errors
+= test_reset_release ();
450 ACE_NEW_RETURN (printer1
,
451 Printer ("I am printer 1"),
454 ACE_Refcounted_Auto_Ptr
<Printer
, ACE_Null_Mutex
> r(printer1
);
455 ACE_Refcounted_Auto_Ptr
<Printer
, ACE_Null_Mutex
> r1(r
);
456 ACE_Refcounted_Auto_Ptr
<Printer
, ACE_Null_Mutex
> r2(r
);
457 ACE_Refcounted_Auto_Ptr
<Printer
, ACE_Null_Mutex
> r3(r
);
458 ACE_Refcounted_Auto_Ptr
<Printer
, ACE_Null_Mutex
> r4(r
);
459 ACE_Refcounted_Auto_Ptr
<Printer
, ACE_Null_Mutex
> r5
= r2
;
460 ACE_Refcounted_Auto_Ptr
<Printer
, ACE_Null_Mutex
> r6
= r1
;
462 if (Printer::instance_count_
== 0)
463 ACE_DEBUG ((LM_DEBUG
,
464 ACE_TEXT ("(%t) Printer instance count is 0; correct\n")));
467 ACE_ERROR ((LM_ERROR
,
468 ACE_TEXT ("(%t) Printer instance count %d; expecting 0\n"),
469 Printer::instance_count_
.value ()));
473 #if defined (ACE_HAS_THREADS)
475 // =========================================================================
476 // The following test uses the ACE_Refcounted_Auto_Ptr in multiple
477 // threads of control.
479 ACE_DEBUG ((LM_DEBUG
,
480 ACE_TEXT ("(%t) performing asynchronous test...\n")));
482 Scheduler
*scheduler_ptr
= 0;
484 // Create active objects..
485 ACE_NEW_RETURN (scheduler_ptr
,
489 std::unique_ptr
<Scheduler
> scheduler(scheduler_ptr
);
491 if (scheduler
->open () == -1)
492 ACE_ERROR_RETURN ((LM_ERROR
,
494 ACE_TEXT ("Error opening scheduler")),
498 ACE_NEW_RETURN (printer1
,
499 Printer ("I am printer 2"),
502 Printer_var
r (printer1
);
504 for (int i
= 0; i
< n_loops
; i
++)
505 // Spawn off the methods, which run in a separate thread as
506 // active object invocations.
507 scheduler
->print (r
);
510 // Close things down.
515 if (Printer::instance_count_
== 0)
516 ACE_DEBUG ((LM_DEBUG
,
517 ACE_TEXT ("(%t) Printer instance count is 0; correct\n")));
520 ACE_ERROR ((LM_ERROR
,
521 ACE_TEXT ("(%t) Printer instance count %d; expecting 0\n"),
522 Printer::instance_count_
.value ()));
526 #endif /* ACE_HAS_THREADS */
528 test_errors
+= test_operator();