Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / tests / Refcounted_Auto_Ptr_Test.cpp
blobbc06ea01139ccb61d7e1a4aeced37b1a884ab8d2
1 //=============================================================================
2 /**
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"
15 #include "ace/ACE.h"
16 #include "ace/Task.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)
28 : message_ (message)
30 this->which_ = ++Printer::current_instance_;
31 ACE_DEBUG ((LM_DEBUG,
32 ACE_TEXT ("(%t) Creating Printer object %d (%C)\n"),
33 this->which_,
34 this->message_));
35 ++Printer::instance_count_;
38 Printer::~Printer ()
40 --Printer::instance_count_;
41 ACE_DEBUG ((LM_DEBUG,
42 ACE_TEXT ("(%t) Deleting Printer object %d (%C)\n"),
43 this->which_,
44 this->message_));
47 void
48 Printer::print ()
50 ACE_DEBUG ((LM_DEBUG,
51 ACE_TEXT ("(%t) %C\n"),
52 this->message_));
55 #if defined (ACE_HAS_THREADS)
57 using Printer_var = ACE_Refcounted_Auto_Ptr<Printer, ACE_Thread_Mutex>;
59 /**
60 * @class Scheduler
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;
72 public:
73 /// Constructor.
74 Scheduler ();
76 //FUZZ: disable check_for_lack_ACE_OS
77 /// Initializer.
78 int open (void *args = 0) override;
80 /// Terminator.
81 int close (u_long flags = 0) override;
82 //FUZZ: enable check_for_lack_ACE_OS
84 /// Destructor.
85 ~Scheduler () override;
87 // = These methods are part of the Active Object Proxy interface.
88 void print (Printer_var &printer);
89 void end ();
91 protected:
92 /// Runs the Scheduler's event loop, which dequeues <Method_Requests>
93 /// and dispatches them.
94 int svc () override;
96 private:
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
108 public:
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;
115 private:
116 Printer_var printer_;
119 Method_Request_print::Method_Request_print (Printer_var &printer)
120 : printer_ (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"),
126 printer_.count ()));
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"),
135 printer_.count ()));
139 Method_Request_print::call ()
141 // Dispatch the Servant's operation and store the result into the
142 // Future.
143 Printer_var temp = printer_;
145 temp->print ();
147 return 0;
151 * @class Method_Request_end
153 * @brief Reification of the <end> method.
155 class Method_Request_end : public ACE_Method_Request
157 public:
158 Method_Request_end (Scheduler *new_Prime_Scheduler);
159 ~Method_Request_end () override;
160 int call () override;
162 private:
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 ();
182 return -1;
185 // Constructor
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")));
196 // Destructor
198 Scheduler::~Scheduler ()
200 ACE_DEBUG ((LM_DEBUG,
201 ACE_TEXT ("(%t) Scheduler will be destroyed\n")));
204 // open
207 Scheduler::open (void *)
209 ACE_DEBUG ((LM_DEBUG,
210 ACE_TEXT ("(%t) Scheduler open\n")));
211 // Become an Active Object.
212 int num_threads = 3;
213 return this->activate (THR_BOUND | THR_JOINABLE, num_threads);
216 // close
219 Scheduler::close (u_long)
221 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) rundown\n")));
222 return 0;
225 // Service..
228 Scheduler::svc ()
230 for (;;)
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 ();
235 if (0 == mo_p)
237 ACE_DEBUG ((LM_DEBUG,
238 ACE_TEXT ("(%t) activation queue shut down\n")));
239 break;
241 std::unique_ptr<ACE_Method_Request> mo (mo_p);
243 ACE_DEBUG ((LM_DEBUG,
244 ACE_TEXT ("(%t) calling method request\n")));
245 // Call it.
246 if(mo->call () == -1)
247 break;
249 // Destructor automatically deletes it.
252 return 0;
255 void
256 Scheduler::end ()
258 this->activation_queue_.enqueue (new Method_Request_end (this));
261 // Here's where the work takes place.
263 void
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,
283 bool expect_null,
284 unsigned int expect_which,
285 int expect_count)
287 if (ptr.null () != expect_null)
289 if (expect_null)
290 ACE_DEBUG ((LM_DEBUG,
291 ACE_TEXT ("Expecting: %s null:: ")
292 ACE_TEXT ("Actual: Printer: %u; Count %d\n"),
293 name,
294 ptr->which_,
295 ptr.count ()));
296 else
297 ACE_ERROR ((LM_ERROR,
298 ACE_TEXT ("Expecting: %s Printer: %u; Count %d:: ")
299 ACE_TEXT ("Actual: Null.\n"),
300 name,
301 expect_which,
302 expect_count));
303 return false;
305 if (ptr.null ())
307 ACE_DEBUG ((LM_DEBUG,
308 ACE_TEXT ("Expecting: %s null:: Actual: Null.\n"),
309 name));
310 return true;
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"),
318 name,
319 expect_which,
320 expect_count,
321 ptr->which_,
322 ptr.count ()));
323 return !fail;
326 static int test_reset_release ()
328 int errors = 0;
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))
334 ++errors;
335 if (!expect (ACE_TEXT ("fum"), fum, false, 1, 1))
336 ++errors;
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))
341 ++errors;
342 if (!expect (ACE_TEXT ("fum"), fum, false, 1, 0))
343 ++errors;
345 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Test release\n")));
346 Printer_Ptr fie(new Printer ("3"));
347 Printer_Ptr foe = fie;
348 foe.release();
349 if (!expect (ACE_TEXT ("fie"), fie, false, 3, 0))
350 ++errors;
351 if (!expect (ACE_TEXT ("foe"), foe, true, 0, 0))
352 ++errors;
354 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Test assignment to null\n")));
355 Printer_Ptr fee(new Printer ("4"));
356 Printer_Ptr eraser;
357 fee = eraser;
358 if (!expect (ACE_TEXT ("fee"), fee, true, 0, 0))
359 ++errors;
360 if (!expect (ACE_TEXT ("eraser"), eraser, true, 0, 0))
361 ++errors;
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"));
366 fix = fax;
367 if (!expect (ACE_TEXT ("fix"), fix, false, 6, 1))
368 ++errors;
369 if (!expect (ACE_TEXT ("fax"), fax, false, 6, 1))
370 ++errors;
372 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Test reset to null\n")));
373 Printer_Ptr fey(new Printer ("7"));
374 Printer_Ptr flo = fey;
375 flo.reset ();
376 if (!expect (ACE_TEXT ("fey"), fey, false, 7, 0))
377 ++errors;
378 if (!expect (ACE_TEXT ("flo"), flo, true, 0, 0))
379 ++errors;
381 return errors;
384 static int test_operator()
386 int errors = 0;
388 // test null
389 Printer_Ptr printer_null;
390 if (!printer_null)
393 else
395 ++errors;
396 ACE_ERROR ((LM_ERROR,
397 ACE_TEXT ("!printer_null should be false\n")));
399 if (printer_null)
401 ++errors;
402 ACE_ERROR ((LM_ERROR,
403 ACE_TEXT ("printer_null should be false\n")));
405 else
409 // test not null
410 Printer_Ptr printer_not_null(new Printer("check not null"));
411 if (!printer_not_null)
413 ++errors;
414 ACE_ERROR ((LM_ERROR,
415 ACE_TEXT ("!printer_not_null should be false\n")));
417 else
420 if (printer_not_null)
423 else
425 ++errors;
426 ACE_ERROR ((LM_ERROR,
427 ACE_TEXT ("printer_not_null should be false\n")));
430 return errors;
434 run_main (int, ACE_TCHAR *[])
436 ACE_START_TEST (ACE_TEXT ("Refcounted_Auto_Ptr_Test"));
438 int test_errors = 0;
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 ();
449 Printer *printer1;
450 ACE_NEW_RETURN (printer1,
451 Printer ("I am printer 1"),
452 -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")));
465 else
467 ACE_ERROR ((LM_ERROR,
468 ACE_TEXT ("(%t) Printer instance count %d; expecting 0\n"),
469 Printer::instance_count_.value ()));
470 ++test_errors;
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,
486 Scheduler (),
487 -1);
489 std::unique_ptr<Scheduler> scheduler(scheduler_ptr);
491 if (scheduler->open () == -1)
492 ACE_ERROR_RETURN ((LM_ERROR,
493 ACE_TEXT ("%p\n"),
494 ACE_TEXT ("Error opening scheduler")),
498 ACE_NEW_RETURN (printer1,
499 Printer ("I am printer 2"),
500 -1);
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.
511 scheduler->end ();
513 scheduler->wait ();
515 if (Printer::instance_count_ == 0)
516 ACE_DEBUG ((LM_DEBUG,
517 ACE_TEXT ("(%t) Printer instance count is 0; correct\n")));
518 else
520 ACE_ERROR ((LM_ERROR,
521 ACE_TEXT ("(%t) Printer instance count %d; expecting 0\n"),
522 Printer::instance_count_.value ()));
523 ++test_errors;
526 #endif /* ACE_HAS_THREADS */
528 test_errors += test_operator();
530 ACE_END_TEST;
532 return test_errors;