Compile fixes
[ACE_TAO.git] / ACE / tests / Bound_Ptr_Test.cpp
blob6f0c2ede69e15b4e2a731be5298f2a42e32d2326
1 //=============================================================================
2 /**
3 * @file Bound_Ptr_Test.cpp
5 * This example tests the <ACE_Strong_Bound_Ptr> and
6 * <ACE_Weak_Bound_Ptr> and illustrates how they may be dispersed
7 * between multiple threads using an implementation of the Active
8 * Object pattern, which is available in the POSA2 book
9 * <http://www.dre.vanderbilt.edu/~schmidt/POSA>.
11 * @author Christopher Kohlhoff <chris@kohlhoff.com>
13 //=============================================================================
15 #include "test_config.h"
16 #include "ace/Null_Mutex.h"
17 #include "ace/Method_Request.h"
18 #include "Bound_Ptr_Test.h"
19 #include "ace/Task.h"
21 // The following Parent and Child classes illustrate how you might use the
22 // ACE_Strong_Bound_Ptr and ACE_Weak_Bound_Ptr together in cyclic
23 // relationships.
24 struct Child_Base
26 virtual ~Child_Base ();
28 // Perform some operation.
29 virtual void do_something () = 0;
32 // This class should only be created on the heap. Normally it would be an
33 // abstract class, and the implementation would be elsewhere.
34 struct Parent
36 Parent ();
37 ~Parent ();
39 // Weak pointer to this object used to hand out new references. Must be
40 // weak since it can't own itself!
41 ACE_Weak_Bound_Ptr<Parent, ACE_Null_Mutex> weak_self_;
43 // The parent owns the child. When the parent is destroyed the child will
44 // be automatically deleted.
45 ACE_Strong_Bound_Ptr<Child_Base, ACE_Null_Mutex> child_;
47 // Called by the child to perform some operation.
48 void do_something ();
50 static size_t instance_count_;
53 // This class should only be created on the heap. Normally it would be an
54 // abstract class, and the implementation would be elsewhere.
55 struct Child : public Child_Base
57 Child (ACE_Weak_Bound_Ptr<Parent, ACE_Null_Mutex> parent);
58 ~Child () override;
60 // Back pointer to the parent. The child does not own the parent so has no
61 // effect on its lifetime.
62 ACE_Weak_Bound_Ptr<Parent, ACE_Null_Mutex> parent_;
64 // Perform some operation. Delegates the work to the parent.
65 void do_something () override;
67 static size_t instance_count_;
70 Child_Base::~Child_Base ()
74 size_t Parent::instance_count_ = 0;
76 Parent::Parent ()
77 : weak_self_(this),
78 child_(new Child(weak_self_))
80 ACE_DEBUG ((LM_DEBUG,
81 ACE_TEXT ("(%t) Creating Parent object\n")));
82 ++Parent::instance_count_;
85 Parent::~Parent ()
87 --Parent::instance_count_;
88 ACE_DEBUG ((LM_DEBUG,
89 ACE_TEXT ("(%t) Deleting Parent object\n")));
92 void Parent::do_something ()
94 ACE_DEBUG ((LM_DEBUG,
95 ACE_TEXT ("(%t) Parent doing something\n")));
98 size_t Child::instance_count_ = 0;
100 Child::Child (ACE_Weak_Bound_Ptr<Parent, ACE_Null_Mutex> parent)
101 : parent_(parent)
103 ACE_DEBUG ((LM_DEBUG,
104 ACE_TEXT ("(%t) Creating Child object\n")));
105 ++Child::instance_count_;
108 Child::~Child ()
110 --Child::instance_count_;
111 ACE_DEBUG ((LM_DEBUG,
112 ACE_TEXT ("(%t) Deleting Child object\n")));
115 void Child::do_something ()
117 ACE_DEBUG ((LM_DEBUG,
118 ACE_TEXT ("(%t) Child doing something\n")));
120 // Using operator-> on a weak pointer will automatically create a strong
121 // pointer as a temporary. This ensures that the object exists for the
122 // lifetime of the call (although it does not check for null).
123 parent_->do_something ();
125 // In cases where we may need to call operations on the weak pointer
126 // many times, we can reduce the overhead by explicitly converting to a
127 // strong pointer first.
128 ACE_Strong_Bound_Ptr<Parent, ACE_Null_Mutex> strong_parent (parent_);
130 // You can check for null to see if the parent object still exists (in this
131 // case it is not strictly necessary since the child will only exist if the
132 // parent still exists).
133 if (strong_parent == 0)
134 return;
136 for (int i = 0; i < 5; ++i)
137 strong_parent->do_something ();
140 size_t Printer::instance_count_ = 0;
142 Printer::Printer (const char *message)
143 : message_ (message)
145 ACE_DEBUG ((LM_DEBUG,
146 ACE_TEXT ("(%t) Creating Printer object\n")));
147 ++Printer::instance_count_;
150 Printer::~Printer ()
152 --Printer::instance_count_;
153 ACE_DEBUG ((LM_DEBUG,
154 ACE_TEXT ("(%t) Deleting Printer object\n")));
157 void
158 Printer::print ()
160 ACE_DEBUG ((LM_DEBUG,
161 ACE_TEXT ("(%t) %C\n"),
162 this->message_));
165 #if defined (ACE_HAS_THREADS)
168 * @class Method_Request_print
170 * @brief Reification of the <print> method.
172 class Method_Request_print : public ACE_Method_Request
174 public:
175 explicit Method_Request_print (Printer_var &printer);
176 ~Method_Request_print () override;
178 /// This is the entry point into the Active Object method.
179 int call () override;
181 private:
182 Printer_var printer_;
185 Method_Request_print::Method_Request_print (Printer_var &printer)
186 : printer_ (printer)
188 ACE_DEBUG ((LM_DEBUG,
189 ACE_TEXT ("(%t) Method_Request_print created\n")));
192 Method_Request_print::~Method_Request_print ()
194 ACE_DEBUG ((LM_DEBUG,
195 ACE_TEXT ("(%t) Method_Request_print will be deleted.\n")));
199 Method_Request_print::call ()
201 // Dispatch the Servant's operation and store the result into the
202 // Future.
203 Printer_var temp = printer_;
205 temp->print ();
207 return 0;
211 * @class Method_Request_end
213 * @brief Reification of the <end> method.
215 class Method_Request_end : public ACE_Method_Request
217 public:
218 Method_Request_end (Scheduler *new_Prime_Scheduler);
219 ~Method_Request_end () override;
220 int call () override;
222 private:
223 Scheduler *scheduler_;
226 Method_Request_end::Method_Request_end (Scheduler *scheduler)
227 : scheduler_ (scheduler)
231 Method_Request_end::~Method_Request_end ()
236 Method_Request_end::call ()
238 // Shut down the scheduler by deactivating the activation queue's
239 // underlying message queue - should pop all worker threads off their
240 // wait and they'll exit.
241 this->scheduler_->msg_queue ()->deactivate ();
242 return -1;
245 // Constructor
246 // Associates the activation queue with this task's message queue,
247 // allowing easy access to the message queue for shutting it down
248 // when it's time to stop this object's service threads.
249 Scheduler::Scheduler ()
250 : activation_queue_ (msg_queue ())
252 ACE_DEBUG ((LM_DEBUG,
253 ACE_TEXT ("(%t) Scheduler created\n")));
256 // Destructor
258 Scheduler::~Scheduler ()
260 ACE_DEBUG ((LM_DEBUG,
261 ACE_TEXT ("(%t) Scheduler will be destroyed\n")));
264 // open
267 Scheduler::open (void *)
269 ACE_DEBUG ((LM_DEBUG,
270 ACE_TEXT ("(%t) Scheduler open\n")));
271 // Become an Active Object.
272 int num_threads = 3;
273 return this->activate (THR_BOUND | THR_JOINABLE, num_threads);
276 // close
279 Scheduler::close (u_long)
281 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) rundown\n")));
282 return 0;
285 // Service..
288 Scheduler::svc ()
290 for (;;)
292 // Dequeue the next method request (we use an strong pointer in
293 // case an exception is thrown in the <call>).
294 ACE_Strong_Bound_Ptr<ACE_Method_Request, ACE_Null_Mutex> mo (this->activation_queue_.dequeue ());
295 if (mo == 0)
297 ACE_DEBUG ((LM_DEBUG,
298 ACE_TEXT ("(%t) activation queue shut down\n")));
299 break;
302 ACE_DEBUG ((LM_DEBUG,
303 ACE_TEXT ("(%t) calling method request\n")));
304 // Call it.
305 if (mo->call () == -1)
306 break;
308 // Destructor automatically deletes it.
311 return 0;
314 void
315 Scheduler::end ()
317 this->activation_queue_.enqueue (new Method_Request_end (this));
320 // Here's where the work takes place.
322 void
323 Scheduler::print (Printer_var &printer)
325 this->activation_queue_.enqueue
326 (new Method_Request_print (printer));
329 // Total number of loops.
330 static int n_loops = 10;
332 #endif /* ACE_HAS_THREADS */
335 run_main (int, ACE_TCHAR *[])
337 ACE_START_TEST (ACE_TEXT ("Bound_Ptr_Test"));
340 // =========================================================================
341 // The following test uses the ACE_Strong_Bound_Ptr in a single
342 // thread of control, hence we use the ACE_Null_Mutex
344 ACE_DEBUG ((LM_DEBUG,
345 ACE_TEXT ("(%t) performing synchronous test...\n")));
347 Parent *parent1 = 0;
348 ACE_NEW_RETURN (parent1,
349 Parent,
350 -1);
351 ACE_Weak_Bound_Ptr<Parent, ACE_Null_Mutex> p8;
353 // Must get the pointer from the parent object's weak_self_ member.
354 ACE_Strong_Bound_Ptr<Parent, ACE_Null_Mutex> p(parent1->weak_self_);
355 ACE_Strong_Bound_Ptr<Parent, ACE_Null_Mutex> p1(p);
356 ACE_Strong_Bound_Ptr<Parent, ACE_Null_Mutex> p2(p);
357 ACE_Weak_Bound_Ptr<Parent, ACE_Null_Mutex> p3(p);
358 ACE_Strong_Bound_Ptr<Parent, ACE_Null_Mutex> p4(p);
359 ACE_Strong_Bound_Ptr<Parent, ACE_Null_Mutex> p5 = p2;
360 ACE_Strong_Bound_Ptr<Parent, ACE_Null_Mutex> p6 = p3;
361 ACE_Weak_Bound_Ptr<Parent, ACE_Null_Mutex> p7(p1);
362 p8 = p2;
363 p->child_->do_something ();
365 ACE_DEBUG ((LM_DEBUG,
366 ACE_TEXT ("(%t) Parent instance count is %d, expecting 0\n"),
367 Parent::instance_count_));
368 if (Parent::instance_count_ != 0)
370 ACE_ERROR_RETURN ((LM_ERROR,
371 ACE_TEXT ("(%t) parent instance count not 0...\n")),
372 -1);
374 ACE_DEBUG ((LM_DEBUG,
375 ACE_TEXT ("(%t) Child instance count is %d, expecting 0\n"),
376 Child::instance_count_));
377 if (Child::instance_count_ != 0)
379 ACE_ERROR_RETURN ((LM_ERROR,
380 ACE_TEXT ("(%t) child instance count not 0...\n")),
381 -1);
383 // Weak pointer should now be set to null.
384 if(!p8.null ())
386 ACE_ERROR_RETURN ((LM_ERROR,
387 ACE_TEXT ("(%t) p8 not nill...\n")),
388 -1);
391 Printer *printer1 = 0;
392 ACE_NEW_RETURN (printer1,
393 Printer ("I am printer 1"),
394 -1);
395 ACE_Weak_Bound_Ptr<Printer, ACE_Null_Mutex> r9;
397 ACE_Strong_Bound_Ptr<Printer, ACE_Null_Mutex> r(printer1);
398 ACE_Strong_Bound_Ptr<Printer, ACE_Null_Mutex> r1(r);
399 ACE_Strong_Bound_Ptr<Printer, ACE_Null_Mutex> r2(r);
400 ACE_Strong_Bound_Ptr<Printer, ACE_Null_Mutex> r3(r);
401 ACE_Strong_Bound_Ptr<Printer, ACE_Null_Mutex> r4(r);
402 ACE_Strong_Bound_Ptr<Printer, ACE_Null_Mutex> r5 = r2;
403 ACE_Strong_Bound_Ptr<Printer, ACE_Null_Mutex> r6 = r1;
404 ACE_Weak_Bound_Ptr<Printer, ACE_Null_Mutex> r7(r1);
405 ACE_Weak_Bound_Ptr<Printer, ACE_Null_Mutex> r8 = r2;
406 r9 = r3;
407 r9->print ();
409 ACE_DEBUG ((LM_DEBUG,
410 ACE_TEXT ("(%t) Printer instance count is %d, expecting 0\n"),
411 Printer::instance_count_));
412 if (Printer::instance_count_ != 0)
414 ACE_ERROR_RETURN ((LM_ERROR,
415 ACE_TEXT ("(%t) Printer instance count not 0...\n")),
416 -1);
418 // Weak pointer should now be set to null.
419 if (!r9.null ())
421 ACE_ERROR_RETURN ((LM_ERROR,
422 ACE_TEXT ("(%t) r9 not nill...\n")),
423 -1);
426 #if defined (ACE_HAS_THREADS)
428 // =========================================================================
429 // The following test uses the ACE_Strong_Bound_Ptr in multiple
430 // threads of control.
432 ACE_DEBUG ((LM_DEBUG,
433 ACE_TEXT ("(%t) performing asynchronous test...\n")));
435 Scheduler *scheduler_ptr = 0;
437 // Create active objects..
438 ACE_NEW_RETURN (scheduler_ptr,
439 Scheduler (),
440 -1);
442 ACE_Strong_Bound_Ptr<Scheduler, ACE_Null_Mutex> scheduler(scheduler_ptr);
444 if (scheduler->open () == -1)
446 ACE_ERROR_RETURN ((LM_ERROR,
447 ACE_TEXT ("(%t) Scheduler open failed...\n")),
448 -1);
452 Printer *printer2 = 0;
453 ACE_NEW_RETURN (printer2,
454 Printer ("I am printer 2"),
455 -1);
457 Printer_var r (printer2);
459 for (int i = 0; i < n_loops; i++)
460 // Spawn off the methods, which run in a separate thread as
461 // active object invocations.
462 scheduler->print (r);
465 // Close things down.
466 scheduler->end ();
468 scheduler->wait ();
470 ACE_DEBUG ((LM_DEBUG,
471 ACE_TEXT ("(%t) Printer instance count is %d, expecting 0\n"),
472 Printer::instance_count_));
473 if (Printer::instance_count_ != 0)
474 return -1;
476 #endif /* ACE_HAS_THREADS */
477 ACE_END_TEST;
479 return 0;