diff options
author | schmidt <douglascraigschmidt@users.noreply.github.com> | 1998-10-17 23:17:54 +0000 |
---|---|---|
committer | schmidt <douglascraigschmidt@users.noreply.github.com> | 1998-10-17 23:17:54 +0000 |
commit | 2322bfac5b4e8bd7aa439c1898101bd533b7acf6 (patch) | |
tree | a7157b70e93f39e9fdfe3bd87c32246ae0baaa25 /tests/Future_Test.cpp | |
parent | 806402a3ce3ed65a9cd491c6cca7129dbeb0a3a4 (diff) | |
download | ATCD-2322bfac5b4e8bd7aa439c1898101bd533b7acf6.tar.gz |
.
Diffstat (limited to 'tests/Future_Test.cpp')
-rw-r--r-- | tests/Future_Test.cpp | 366 |
1 files changed, 233 insertions, 133 deletions
diff --git a/tests/Future_Test.cpp b/tests/Future_Test.cpp index fe9fc3e76bb..9dfadb59700 100644 --- a/tests/Future_Test.cpp +++ b/tests/Future_Test.cpp @@ -9,11 +9,15 @@ // Future_Test.cpp // // = DESCRIPTION -// This example tests the ACE Future. +// This example tests the ACE Future and illustrates an +// implementation of the Active Object pattern, which is available +// at <http://www.cs.wustl.edu/~schmidt/Act-Obj.ps.gz>. The +// Active Object itself is very simple -- it determines if numbers +// are prime. // // = AUTHOR // Andres Kruse <Andres.Kruse@cern.ch>, Douglas C. Schmidt -// <schmidt@cs.wustl.edu> and Per Andersson <pera@ipso.se> +// <schmidt@cs.wustl.edu>, and Per Andersson <pera@ipso.se> // // ============================================================================ @@ -23,7 +27,7 @@ #include "ace/Synch.h" #include "ace/Message_Queue.h" #include "ace/Future.h" -#include "ace/Method_Object.h" +#include "ace/Method_Request.h" #include "ace/Activation_Queue.h" #include "ace/Auto_Ptr.h" @@ -38,195 +42,256 @@ USELIB("..\ace\aced.lib"); typedef ACE_Atomic_Op<ACE_Thread_Mutex, int> ATOMIC_INT; -// a counter for the tasks.. +// A counter for the tasks.. static ATOMIC_INT task_count (0); -// a counter for the futures.. +// A counter for the futures.. static ATOMIC_INT future_count (0); -// a counter for the capsules.. +// A counter for the capsules.. static ATOMIC_INT capsule_count (0); -// a counter for the method objects... -static ATOMIC_INT methodobject_count (0); +// A counter for the method requests... +static ATOMIC_INT method_request_count (0); -class Scheduler : public ACE_Task_Base - // = TITLE - // Active Object Scheduler. +class Prime_Scheduler : public ACE_Task_Base { + // = TITLE + // Prime number scheduler for the Active Object. + // + // = DESCRIPTION + // This class also plays the role of the Proxy and the Servant + // in the Active Object pattern. Naturally, these roles could + // be split apart from the Prime_Scheduler. public: - Scheduler (const ASYS_TCHAR *, Scheduler * = 0); - virtual ~Scheduler (void); + // = Initialization and termination methods. + Prime_Scheduler (const ASYS_TCHAR *, + Prime_Scheduler * = 0); + // Constructor. virtual int open (void *args = 0); + // Initializer. + virtual int close (u_long flags = 0); - virtual int svc (void); + // Terminator. + virtual ~Prime_Scheduler (void); + // Destructor. + + // = These methods are part of the Active Object Proxy interface. ACE_Future<u_long> work (u_long param, int count = 1); ACE_Future<const ASYS_TCHAR*> name (void); void end (void); +protected: + virtual int svc (void); + // Runs the Prime_Scheduler's event loop, which dequeues + // <Method_Requests> and dispatches them. + + // = These are the Servant methods that do the actual work. u_long work_i (u_long, int); const ASYS_TCHAR *name_i (void); private: + // = These are the <Prime_Scheduler> implementation details. ASYS_TCHAR *name_; ACE_Activation_Queue activation_queue_; - Scheduler *scheduler_; + Prime_Scheduler *scheduler_; }; -class Method_Object_work : public ACE_Method_Object +class Method_Request_work : public ACE_Method_Request +{ // = TITLE // Reification of the <work> method. -{ public: - Method_Object_work (Scheduler *, u_long, int, ACE_Future<u_long> &); - virtual ~Method_Object_work (void); + Method_Request_work (Prime_Scheduler *, + u_long, + int, + ACE_Future<u_long> &); + virtual ~Method_Request_work (void); + virtual int call (void); + // This is the entry point into the Active Object method. private: - Scheduler *scheduler_; + Prime_Scheduler *scheduler_; + u_long param_; + // Parameter to the method that's used to determine if a number if + // prime. + int count_; + // Unused. + ACE_Future<u_long> future_result_; + // Store the result of the Future. }; -Method_Object_work::Method_Object_work (Scheduler* new_Scheduler, - u_long new_param, - int new_count, - ACE_Future<u_long> &new_result) - : scheduler_ (new_Scheduler), +Method_Request_work::Method_Request_work (Prime_Scheduler *new_Prime_Scheduler, + u_long new_param, + int new_count, + ACE_Future<u_long> &new_result) + : scheduler_ (new_Prime_Scheduler), param_ (new_param), count_ (new_count), future_result_ (new_result) { ACE_DEBUG ((LM_DEBUG, - ASYS_TEXT ("(%t) Method_Object_work created\n"))); + ASYS_TEXT ("(%t) Method_Request_work created\n"))); } -Method_Object_work::~Method_Object_work (void) +Method_Request_work::~Method_Request_work (void) { ACE_DEBUG ((LM_DEBUG, - ASYS_TEXT ("(%t) Method_Object_work will be deleted.\n"))); + ASYS_TEXT ("(%t) Method_Request_work will be deleted.\n"))); } - int -Method_Object_work::call (void) +Method_Request_work::call (void) { - return this->future_result_.set - (this->scheduler_->work_i (this->param_, - this->count_)); + // Dispatch the Servant's operation and store the result into the + // Future. + return this->future_result_.set (this->scheduler_->work_i + (this->param_, + this->count_)); } -class Method_Object_name : public ACE_Method_Object +class Method_Request_name : public ACE_Method_Request +{ // = TITLE // Reification of the <name> method. -{ public: - Method_Object_name (Scheduler *, - ACE_Future<const ASYS_TCHAR*> &); - virtual ~Method_Object_name (void); + Method_Request_name (Prime_Scheduler *, + ACE_Future<const ASYS_TCHAR*> &); + virtual ~Method_Request_name (void); + virtual int call (void); + // This is the entry point into the Active Object method. private: - Scheduler *scheduler_; + Prime_Scheduler *scheduler_; ACE_Future<const ASYS_TCHAR*> future_result_; }; -Method_Object_name::Method_Object_name (Scheduler *new_scheduler, - ACE_Future<const ASYS_TCHAR*> &new_result) +Method_Request_name::Method_Request_name (Prime_Scheduler *new_scheduler, + ACE_Future<const ASYS_TCHAR*> &new_result) : scheduler_ (new_scheduler), future_result_ (new_result) { ACE_DEBUG ((LM_DEBUG, - ASYS_TEXT ("(%t) Method_Object_name created\n"))); + ASYS_TEXT ("(%t) Method_Request_name created\n"))); } -Method_Object_name::~Method_Object_name (void) +Method_Request_name::~Method_Request_name (void) { ACE_DEBUG ((LM_DEBUG, - ASYS_TEXT ("(%t) Method_Object_name will be deleted.\n"))); + ASYS_TEXT ("(%t) Method_Request_name will be deleted.\n"))); } int -Method_Object_name::call (void) +Method_Request_name::call (void) { + // Dispatch the Servant's operation and store the result into the + // Future. return future_result_.set (scheduler_->name_i ()); } -class Method_Object_end : public ACE_Method_Object +class Method_Request_end : public ACE_Method_Request +{ // = TITLE // Reification of the <end> method. -{ public: - Method_Object_end (Scheduler *new_Scheduler) - : scheduler_ (new_Scheduler) {} - virtual ~Method_Object_end (void) {} + Method_Request_end (Prime_Scheduler *new_Prime_Scheduler) + : scheduler_ (new_Prime_Scheduler) {} + virtual ~Method_Request_end (void) {} virtual int call (void) { this->scheduler_->close (); return -1; } private: - Scheduler *scheduler_; + Prime_Scheduler *scheduler_; }; -// constructor -Scheduler::Scheduler (const ASYS_TCHAR *newname, - Scheduler *new_Scheduler) +Method_Request_end::Method_Request_end (Prime_Scheduler *scheduler) + : scheduler_ (scheduler) +{ +} + +Method_Request_end::~Method_Request_end (void) +{ +} + +int +Method_Request_end::call (void) { - ACE_NEW (this->name_, ASYS_TCHAR[ACE_OS::strlen (newname) + 1]); - ACE_OS::strcpy ((ASYS_TCHAR *) this->name_, newname); - this->scheduler_ = new_Scheduler; + // Shut down the scheduler. + this->scheduler_->close (); + return -1; +} + +// Constructor +Prime_Scheduler::Prime_Scheduler (const ASYS_TCHAR *newname, + Prime_Scheduler *new_scheduler) + : scheduler_ (new_scheduler) +{ + ACE_NEW (this->name_, + ASYS_TCHAR[ACE_OS::strlen (newname) + 1]); + ACE_OS::strcpy ((ASYS_TCHAR *) this->name_, + newname); ACE_DEBUG ((LM_DEBUG, - ASYS_TEXT ("(%t) Scheduler %s created\n"), + ASYS_TEXT ("(%t) Prime_Scheduler %s created\n"), this->name_)); } // Destructor -Scheduler::~Scheduler (void) + +Prime_Scheduler::~Prime_Scheduler (void) { ACE_DEBUG ((LM_DEBUG, - ASYS_TEXT ("(%t) Scheduler %s will be destroyed\n"), + ASYS_TEXT ("(%t) Prime_Scheduler %s will be destroyed\n"), this->name_)); - delete[] this->name_; + delete [] this->name_; } // open + int -Scheduler::open (void *) +Prime_Scheduler::open (void *) { task_count++; ACE_DEBUG ((LM_DEBUG, - ASYS_TEXT ("(%t) Scheduler %s open\n"), + ASYS_TEXT ("(%t) Prime_Scheduler %s open\n"), this->name_)); // Become an Active Object. return this->activate (THR_BOUND | THR_DETACHED); } // close + int -Scheduler::close (u_long) +Prime_Scheduler::close (u_long) { ACE_DEBUG ((LM_DEBUG, - ASYS_TEXT ("(%t) Scheduler %s close\n"), + ASYS_TEXT ("(%t) Prime_Scheduler %s close\n"), this->name_)); task_count--; return 0; } -// service.. +// Service.. + int -Scheduler::svc (void) +Prime_Scheduler::svc (void) { for (;;) { - // Dequeue the next method object (we use an auto pointer in + // Dequeue the next method request (we use an auto pointer in // case an exception is thrown in the <call>). - auto_ptr<ACE_Method_Object> mo (this->activation_queue_.dequeue ()); + auto_ptr<ACE_Method_Request> mo (this->activation_queue_.dequeue ()); - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%t) calling method object\n"))); + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("(%t) calling method request\n"))); // Call it. if (mo->call () == -1) break; @@ -238,16 +303,17 @@ Scheduler::svc (void) } void -Scheduler::end (void) +Prime_Scheduler::end (void) { - this->activation_queue_.enqueue (new Method_Object_end (this)); + this->activation_queue_.enqueue (new Method_Request_end (this)); } +// Here's where the Work takes place. We compute if the parameter is +// a prime number. -// Here's where the Work takes place. u_long -Scheduler::work_i (u_long param, - int count) +Prime_Scheduler::work_i (u_long param, + int count) { ACE_UNUSED_ARG (count); @@ -255,16 +321,16 @@ Scheduler::work_i (u_long param, } const ASYS_TCHAR * -Scheduler::name_i (void) +Prime_Scheduler::name_i (void) { return this->name_; } ACE_Future<const ASYS_TCHAR *> -Scheduler::name (void) +Prime_Scheduler::name (void) { if (this->scheduler_) - // Delegate to the Scheduler. + // Delegate to the Prime_Scheduler. return this->scheduler_->name (); else { @@ -272,14 +338,15 @@ Scheduler::name (void) // @@ What happens if new fails here? this->activation_queue_.enqueue - (new Method_Object_name (this, new_future)); - + (new Method_Request_name (this, + new_future)); return new_future; } } ACE_Future<u_long> -Scheduler::work (u_long newparam, int newcount) +Prime_Scheduler::work (u_long newparam, + int newcount) { if (this->scheduler_) { return this->scheduler_->work (newparam, newcount); @@ -288,8 +355,10 @@ Scheduler::work (u_long newparam, int newcount) ACE_Future<u_long> new_future; this->activation_queue_.enqueue - (new Method_Object_work (this, newparam, - newcount, new_future)); + (new Method_Request_work (this, + newparam, + newcount, + new_future)); return new_future; } } @@ -307,8 +376,8 @@ template class ACE_Future<u_long>; template class ACE_Future_Rep<ASYS_TCHAR const *>; template class ACE_Future_Rep<int>; template class ACE_Future_Rep<u_long>; -template class auto_ptr<ACE_Method_Object>; -template class ACE_Auto_Basic_Ptr<ACE_Method_Object>; +template class auto_ptr<ACE_Method_Request>; +template class ACE_Auto_Basic_Ptr<ACE_Method_Request>; #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) #pragma instantiate ACE_Atomic_Op<ACE_Thread_Mutex, int> #pragma instantiate ACE_Future<const ASYS_TCHAR *> @@ -317,8 +386,8 @@ template class ACE_Auto_Basic_Ptr<ACE_Method_Object>; #pragma instantiate ACE_Future_Rep<ASYS_TCHAR const *> #pragma instantiate ACE_Future_Rep<int> #pragma instantiate ACE_Future_Rep<u_long> -#pragma instantiate auto_ptr<ACE_Method_Object> -#pragma instantiate ACE_Auto_Basic_Ptr<ACE_Method_Object> +#pragma instantiate auto_ptr<ACE_Method_Request> +#pragma instantiate ACE_Auto_Basic_Ptr<ACE_Method_Request> #endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ #endif /* ACE_HAS_THREADS */ @@ -329,38 +398,52 @@ main (int, ASYS_TCHAR *[]) ACE_START_TEST (ASYS_TEXT ("Future_Test")); #if defined (ACE_HAS_THREADS) - Scheduler *andres, *peter, *helmut, *matias; + // @@ Should make these be <auto_ptr>s... + Prime_Scheduler *andres, *peter, *helmut, *matias; // Create active objects.. - // @@ Should "open" be subsumed within the constructor of - // Scheduler()? - ACE_NEW_RETURN (andres, Scheduler (ASYS_TEXT ("andres")), -1); - andres->open (); - ACE_NEW_RETURN (peter, Scheduler (ASYS_TEXT ("peter")), -1); - peter->open (); - ACE_NEW_RETURN (helmut, Scheduler (ASYS_TEXT ("helmut")), -1); - helmut->open (); + ACE_NEW_RETURN (andres, + Prime_Scheduler (ASYS_TEXT ("andres")), + -1); + ACE_ASSERT (andres->open () != -1); + ACE_NEW_RETURN (peter, + Prime_Scheduler (ASYS_TEXT ("peter")), + -1); + ACE_ASSERT (peter->open () != -1); + ACE_NEW_RETURN (helmut, + Prime_Scheduler (ASYS_TEXT ("helmut")), + -1); + ACE_ASSERT (helmut->open () != -1); // Matias passes all asynchronous method calls on to Andres... - ACE_NEW_RETURN (matias, Scheduler (ASYS_TEXT ("matias"), andres), -1); - matias->open (); + ACE_NEW_RETURN (matias, + Prime_Scheduler (ASYS_TEXT ("matias"), + andres), + -1); + ACE_ASSERT (matias->open ()); for (int i = 0; i < n_loops; i++) { { - ACE_Future<u_long> fresulta, fresultb, fresultc, fresultd, fresulte; - ACE_Future<const ASYS_TCHAR*> fname; + ACE_Future<u_long> fresulta; + ACE_Future<u_long> fresultb; + ACE_Future<u_long> fresultc; + ACE_Future<u_long> fresultd; + ACE_Future<u_long> fresulte; + ACE_Future<const ASYS_TCHAR *> fname; ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%t) going to do a non-blocking call\n"))); + // Spawn off the methods, which run in a separate thread as + // active object invocations. fresulta = andres->work (9013); fresultb = peter->work (9013); fresultc = helmut->work (9013); fresultd = matias->work (9013); fname = andres->name (); - // see if the result is available... + // See if the result is available... if (fresulta.ready ()) ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%t) wow.. work is ready.....\n"))); @@ -374,8 +457,8 @@ main (int, ASYS_TCHAR *[]) if (i % 3 == 0) { - // Every 3rd time... disconnect the futures... - // but "fresulte" should still contain the result... + // Every 3rd time... disconnect the futures... but + // "fresulte" should still contain the result... fresulta.cancel (10ul); fresultb.cancel (20ul); fresultc.cancel (30ul); @@ -390,26 +473,33 @@ main (int, ASYS_TCHAR *[]) fresultd.get (resultd); fresulte.get (resulte); - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%t) result a %u\n"), (u_int) resulte)); - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%t) result b %u\n"), (u_int) resulta)); - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%t) result c %u\n"), (u_int) resultb)); - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%t) result d %u\n"), (u_int) resultc)); - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%t) result e %u\n"), (u_int) resultd)); + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("(%t) result a %u\n") + ASYS_TEXT ("(%t) result b %u\n") + ASYS_TEXT ("(%t) result c %u\n") + ASYS_TEXT ("(%t) result d %u\n") + ASYS_TEXT ("(%t) result e %u\n"), + (u_int) resulta, + (u_int) resultb, + (u_int) resultc, + (u_int) resulte, + (u_int) resultd)); const ASYS_TCHAR *name; - fname.get (name); - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("(%t) name %s\n"), name)); - + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("(%t) name %s\n"), + name)); } ACE_DEBUG ((LM_DEBUG, - ASYS_TEXT ("(%t) task_count %d future_count %d capsule_count %d methodobject_count %d\n"), + ASYS_TEXT ("(%t) task_count %d future_count %d") + ASYS_TEXT ("capsule_count %d method_request_count %d\n"), task_count.value (), future_count.value (), capsule_count.value (), - methodobject_count.value ())); + method_request_count.value ())); } // Close things down. @@ -421,24 +511,25 @@ main (int, ASYS_TCHAR *[]) ACE_OS::sleep (2); ACE_DEBUG ((LM_DEBUG, - ASYS_TEXT ("(%t) task_count %d future_count %d capsule_count %d methodobject_count %d\n"), + ASYS_TEXT ("(%t) task_count %d future_count %d") + ASYS_TEXT ("capsule_count %d method_request_count %d\n"), task_count.value (), future_count.value (), capsule_count.value (), - methodobject_count.value ())); - + method_request_count.value ())); { - // Check if set then get works, older versions of ACE_Future - // will lock forever (or until the timer expires), will use a small - // timer value to avoid blocking the process. + // Check if set then get works, older versions of <ACE_Future> + // will lock forever (or until the timer expires), will use a + // small timer value to avoid blocking the process. ACE_Future<int> f1; - f1.set(100); + f1.set (100); - ACE_Time_Value timeout(1); + ACE_Time_Value timeout (1); int value = 0; - if (f1.get (value, &timeout) == 0 && value == 100) + if (f1.get (value, &timeout) == 0 + && value == 100) ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("Ace_Future<T>::Set followed by Ace_Future<T>::Get works.\n"))); else @@ -450,21 +541,24 @@ main (int, ASYS_TCHAR *[]) ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("Checking if Ace_Future<T>::operator= is implemented ") ASYS_TEXT ("incorrectly this might crash the program.\n"))); - ACE_Future<int> f1; { - ACE_Future<int> f2 (f1); // To ensure that a rep object is created + // To ensure that a rep object is created. + ACE_Future<int> f2 (f1); } // Now it is one ACE_Future<int> referencing the rep instance - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("0.\n"))); - //check that self assignment works + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("0.\n"))); + + //Check that self assignment works. f1 = f1; + // Is there any repesentation left, and if so what is the ref // count older ACE_Future<> implementations have deleted the rep // instance at this moment - // The stuff below might crash the process if the op= + // The stuff below might crash the process if the <operator=> // implementation was bad int value = 0; ACE_Time_Value timeout (1); @@ -472,33 +566,39 @@ main (int, ASYS_TCHAR *[]) f1.set (100); f1.get (value, &timeout); - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("1.\n"))); - { // Might delete the same data a couple of times + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("1.\n"))); + { + // Might delete the same data a couple of times. ACE_Future<int> f2 (f1); f1.set (100); f1.get (value, &timeout); } - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("2.\n"))); + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("2.\n"))); { ACE_Future<int> f2 (f1); f1.set (100); f1.get (value, &timeout); } - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("3.\n"))); + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("3.\n"))); { ACE_Future<int> f2 (f1); f1.set (100); f1.get (value, &timeout); } - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("4.\n"))); + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("4.\n"))); { ACE_Future<int> f2 (f1); f1.set (100); f1.get (value, &timeout); } - ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("5.\n"))); + ACE_DEBUG ((LM_DEBUG, + ASYS_TEXT ("5.\n"))); { ACE_Future<int> f2 (90); f2.get (value, &timeout); |