diff options
-rw-r--r-- | ace/Future.cpp | 198 | ||||
-rw-r--r-- | ace/Future.h | 54 | ||||
-rw-r--r-- | ace/Map_Manager.h | 8 | ||||
-rw-r--r-- | apps/Gateway/Gateway/proxy_config | 2 |
4 files changed, 118 insertions, 144 deletions
diff --git a/ace/Future.cpp b/ace/Future.cpp index 7c5fd9b29af..d240a9adc42 100644 --- a/ace/Future.cpp +++ b/ace/Future.cpp @@ -24,6 +24,7 @@ ACE_Future_Rep<T>::dump (void) const ACE_DEBUG ((LM_DEBUG," (NON-NULL)\n")); else ACE_DEBUG ((LM_DEBUG," (NULL)\n")); + ACE_DEBUG ((LM_INFO,"value_ready_: \n")); this->value_ready_.dump (); ACE_DEBUG ((LM_INFO,"value_ready_mutex_: \n")); @@ -31,6 +32,39 @@ ACE_Future_Rep<T>::dump (void) const ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } +template <class T> ACE_Future_Rep<T> * +ACE_Future_Rep<T>::create (void) +{ + // Yes set ref count to zero. + ACE_NEW_RETURN (((ACE_Future<T> *) this)->future_rep_, ACE_Future_Rep<T>, 0); +} + +template <class T> ACE_Future_Rep<T> * +ACE_Future_Rep<T>::attach (ACE_Future_Rep<T> *rep) +{ + ACE_ASSERT (rep != 0); + // Use value_ready_mutex_ for both condition and ref count management + ACE_MT (ACE_GUARD (ACE_Thread_Mutex, r_mon, (ACE_Thread_Mutex &) rep->value_ready_mutex_)); + ++rep->ref_count_; + return rep; +} + +template <class T> void +ACE_Future_Rep<T>::detach (ACE_Future_Rep<T> *rep) +{ + ACE_ASSERT(rep != 0); + // Use value_ready_mutex_ for both condition and ref count management + ACE_MT (ACE_GUARD (ACE_Thread_Mutex, r_mon, (ACE_Thread_Mutex &) rep->value_ready_mutex_)); + + if (rep->ref_count_-- == 0) + { + r_mon.release (); + // We do not need the lock when deleting the representation. + // There should be no side effects from deleting rep. + delete rep; + } +} + template <class T> ACE_Future_Rep<T>::ACE_Future_Rep (void) : value_ (0), @@ -43,7 +77,6 @@ template <class T> ACE_Future_Rep<T>::~ACE_Future_Rep (void) { delete this->value_; - this->value_ = 0; } template <class T> int @@ -74,7 +107,8 @@ ACE_Future_Rep<T>::set (const T &r) } template <class T> int -ACE_Future_Rep<T>::get (T &value, ACE_Time_Value *tv) +ACE_Future_Rep<T>::get (T &value, + ACE_Time_Value *tv) { // If the value is already produced, return it. if (this->value_ == 0) @@ -85,11 +119,10 @@ ACE_Future_Rep<T>::get (T &value, ACE_Time_Value *tv) // producer writes to it. while (this->value_ == 0) - { - // Perform a timed wait. - if (this->value_ready_.wait (tv) == -1) - return -1; - } + // Perform a timed wait. + if (this->value_ready_.wait (tv) == -1) + return -1; + // Destructor releases the lock. } @@ -109,82 +142,47 @@ ACE_Future_Rep<T>::operator T () // If the value is not yet defined we must block until the // producer writes to it. + // Wait ``forever.'' + while (this->value_ == 0) - { - // wait forever - if (this->value_ready_.wait () == -1) - // What to do in this case since we've got to indicate - // failure somehow? Exceptions would be nice, but they're - // not portable... - return 0; - } + if (this->value_ready_.wait () == -1) + // What to do in this case since we've got to indicate + // failure somehow? Exceptions would be nice, but they're + // not portable... + return 0; // Destructor releases the mutex - } return *this->value_; } - template <class T> ACE_Future<T>::ACE_Future (void) - : future_rep_ (0) + : future_rep_ (Future_Rep::create ()) { } template <class T> ACE_Future<T>::ACE_Future (const ACE_Future<T> &r) + : future_rep_ (Future_Rep::attach (r.future_rep_)) { - - // copy constructor: - // - // bind <this> to the same <ACE_Future_Rep> as <r>. - - // @@ not really clear if this is needed... after all this - // ACE_Future is just being instantiated... - ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->mutex_)); - - // acquire the mutex on <r>. We have to make sure - // that <r> does not delete its future_rep_... - - ACE_MT (ACE_GUARD (ACE_Thread_Mutex, r_mon, (ACE_Thread_Mutex &) r.mutex_)); - - // Check if 'r' has already a ACE_Future_rep bound to it. - if (r.future_rep_ == 0) - this->future_rep_ = r.create_rep_i (); - else - // ACE_Future_rep exists already, we can just link to it. - this->future_rep_ = r.future_rep_; - - this->future_rep_->ref_count_++; - } template <class T> ACE_Future<T>::ACE_Future (const T &r) + : future_rep_ (Future_Rep::create ()) { ACE_DEBUG ((LM_DEBUG," (%t) funny constructor\n")); ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->mutex_)); - this->create_rep_i ()->set (r); + this->future_rep_->set (r); } template <class T> ACE_Future<T>::~ACE_Future (void) { ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->mutex_)); - - if (this->future_rep_) - { - this->future_rep_->ref_count_--; - - if (this->future_rep_->ref_count_ == 0) - { - delete this->future_rep_; - this->future_rep_ = 0; - } - } - + Future_Rep::detach (future_rep_); } template <class T> int @@ -202,53 +200,34 @@ ACE_Future<T>::operator!= (const ACE_Future<T> &r) const template <class T> int ACE_Future<T>::cancel (const T &r) { - ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->mutex_, -1)); + this->cancel (); + return this->future_rep_->set (r); +} +template <class T> void +ACE_Future<T>::cancel (void) +{ + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->mutex_, -1)); + // If this ACE_Future is already attached to a ACE_Future_Rep, // detach it (maybe delete the ACE_Future_Rep). - if (this->future_rep_) - { - this->future_rep_->ref_count_--; - - if (this->future_rep_->ref_count_ == 0) - delete this->future_rep_; - } - - // Make a new ACE_Future_Rep and immediately assign - // the new value to it. - this->create_rep_i (); - return this->future_rep_->set (r); + Future_Rep *new_rep (Future_Rep::create ()); + Future_Rep *old_rep (this->future_rep_); + this->future_rep_ = new_rep; + Future_Rep::detach (old_rep); } template <class T> int ACE_Future<T>::set (const T &r) { - if (this->future_rep_) - // Give the pointer to the result to the ACE_Future_Rep. - return this->future_rep_->set (r); - else - // @@ Maybe this should return a special value to indicate that - // there's no <ACE_Future_Rep> yet? - return 0; -} - -template <class T> ACE_Future_Rep<T> * -ACE_Future<T>::create_rep_i (void) const -{ - // Should only be called internally with locks held. - ACE_NEW_RETURN (((ACE_Future<T> *) this)->future_rep_, ACE_Future_Rep<T>, 0); - this->future_rep_->ref_count_ = 1; - return this->future_rep_; + // Give the pointer to the result to the ACE_Future_Rep. + return this->future_rep_->set (r); } - template <class T> int ACE_Future<T>::ready (void) { // We're ready if the ACE_Future_rep is ready... - if (this->future_rep_) - return this->future_rep_->ready (); - else - return 0; + return this->future_rep_->ready (); } template <class T> int @@ -256,10 +235,6 @@ ACE_Future<T>::get (T &value, ACE_Time_Value *tv) { ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->mutex_, -1)); - if (this->future_rep_ == 0) - // Oops, we have to create a ACE_Future_Rep first. - this->create_rep_i (); - // We return the ACE_Future_rep. return this->future_rep_->get (value, tv); } @@ -289,32 +264,21 @@ ACE_Future<T>::operator = (const ACE_Future<T> &r) // // bind <this> to the same <ACE_Future_Rep> as <r>. + Future_Rep *new_rep = 0; + { + // This will work if &r == this + // and if not it will keep the r.mutex_ locked for as little + // time as possible + ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, r.mutex_)); + new_rep = Future_Rep::attach (r.future_rep_); + } + ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->mutex_)); - // if there is already a <ACE_Future_Rep> we have - // to disconnect from it... - if (this->future_rep_) - { - // Disconnect from the <ACE_Future_Rep>. - this->future_rep_->ref_count_--; - - if (this->future_rep_->ref_count_ == 0) - delete this->future_rep_; - } - - // Acquire the mutex on <r>. We have to make sure - // that <r> does not delete it's future_rep_... - - ACE_MT (ACE_GUARD (ACE_Thread_Mutex, r_mon, (ACE_Thread_Mutex &) r.mutex_)); - - // Check if 'r' has already a ACE_Future_rep bound to it. - if (r.future_rep_ == 0) - this->future_rep_ = r.create_rep_i (); - else - // ACE_Future_rep exists already, we can just link to it. - this->future_rep_ = r.future_rep_; - - this->future_rep_->ref_count_++; + Future_Rep *old_rep = this->future_rep_; + this->future_rep_ = new_rep; + // Setup the new rep before detaching old rep for exception safety. + Future_Rep::detach (old_rep); } template <class T> void @@ -346,6 +310,8 @@ ACE_Future<T>::operator &() } #if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION) +// This should probably be moved elsewhere now that ACE_Atomic_Op<> +// isn't used. template class ACE_Atomic_Op<ACE_Thread_Mutex, int>; #endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */ diff --git a/ace/Future.h b/ace/Future.h index a296a91c632..ab371b97323 100644 --- a/ace/Future.h +++ b/ace/Future.h @@ -1,7 +1,6 @@ /* -*- C++ -*- */ // $Id$ - // ============================================================================ // // = LIBRARY @@ -11,8 +10,9 @@ // Future.h // // = AUTHOR -// Andres Kruse <Andres.Kruse@cern.ch> and Douglas C. Schmidt -// <schmidt@cs.wustl.edu> +// Andres Kruse <Andres.Kruse@cern.ch>, Douglas C. Schmidt +// <schmidt@cs.wustl.edu>, and Per Andersson +// <Per.Andersson@hfera.ericsson.se>. // // ============================================================================ @@ -27,20 +27,22 @@ template <class T> class ACE_Future; template <class T> class ACE_Future_Rep -// = TITLE -// -// ACE_Future_Rep<T> -// -// = DESCRIPTION -// An ACE_Future_Rep<T> object encapsules a pointer to an -// object of class T which is the result of an asynchronous -// method invocation. It is pointed to by ACE_Future<T> object[s] -// and only accessible through them. + // = TITLE + // ACE_Future_Rep<T> + // + // = DESCRIPTION + // An ACE_Future_Rep<T> object encapsules a pointer to an + // object of class T which is the result of an asynchronous + // method invocation. It is pointed to by ACE_Future<T> object[s] + // and only accessible through them. { friend class ACE_Future<T>; private: - + static ACE_Future_Rep<T> *create (void); + static ACE_Future_Rep<T> *attach (ACE_Future_Rep<T> *rep); + static void detach (ACE_Future_Rep<T> *rep); + int set (const T &r); // Set the result value. @@ -72,7 +74,8 @@ private: T *value_; // Pointer to the result. - ACE_Atomic_Op<ACE_Thread_Mutex, int> ref_count_; + int ref_count_; +// ACE_Atomic_Op<ACE_Thread_Mutex, int> ref_count_; // Reference count. // = Condition variable and mutex that protect the <value_>. @@ -82,9 +85,10 @@ private: template <class T> class ACE_Future // = TITLE - // This class implements a ``single write, multiple read'' pattern - // that can be used to return results from asynchronous method - // invocations. + // This class implements a ``single write, multiple read'' + // pattern that can be used to return results from asynchronous + // method invocations. + // // = DESCRIPTION { public: @@ -110,6 +114,10 @@ public: int cancel (const T &r); // Cancel an <ACE_Future> and assign the value <r>. It is used if a // client does not want to wait for <T> to be produced. + + void cancel (void); + // Cancel an <ACE_Future>. This puts the future into its initial + // state. int operator == (const ACE_Future<T> &r) const; // Equality operator that returns 1 if both ACE_Future<T> objects @@ -146,24 +154,21 @@ public: // Declare the dynamic allocation hooks. private: - ACE_Future_Rep<T> *create_rep_i (void) const; - // Create the <ACE_Future_Rep> object. - - void* operator new (size_t nbytes); + void *operator new (size_t nbytes); // Do not allow new operator. - void operator delete(void *); + void operator delete (void *); // Do not allow delete operator void operator &(); // Do not allow address-of operator. - ACE_Future_Rep<T> *future_rep_; // the ACE_Future_Rep + typedef ACE_Future_Rep<T> Future_Rep; + Future_Rep* future_rep_; ACE_Thread_Mutex mutex_; // Protect operations on the <Future>. - }; #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) @@ -173,5 +178,6 @@ private: #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) #pragma implementation ("Future.cpp") #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + #endif /* ACE_HAS_THREADS */ #endif /* ACE_FUTURE_H */ diff --git a/ace/Map_Manager.h b/ace/Map_Manager.h index 74ec2902f33..d9d1ea56ea1 100644 --- a/ace/Map_Manager.h +++ b/ace/Map_Manager.h @@ -140,11 +140,13 @@ public: int unbind (const EXT_ID &ext_id); // Unbind (remove) the <ext_id> from the map. Don't return the // <int_id> to the caller (this is useful for collections where the - // <int_id>s are *not* dynamically allocated...) + // <int_id>s are *not* dynamically allocated...) Returns 0 if + // successful, else -1. int unbind (const EXT_ID &ext_id, INT_ID &int_id); - // Break any association of <ext_id>. Returns the value of <int_id> in - // case the caller needs to deallocate memory. + // Break any association of <ext_id>. Returns the value of <int_id> + // in case the caller needs to deallocate memory. Returns 0 if + // successful, else -1. size_t current_size (void); // Return the current size of the map. diff --git a/apps/Gateway/Gateway/proxy_config b/apps/Gateway/Gateway/proxy_config index e0784e4038e..54343cb0e73 100644 --- a/apps/Gateway/Gateway/proxy_config +++ b/apps/Gateway/Gateway/proxy_config @@ -35,7 +35,7 @@ # ID Port Role Timeout Port # ---- -------- ------ ------ ---------- ----- -------- 1 merengue.cs 10010 S 32 0 1 - 2 tango.cs 10010 C 32 0 1 + 2 flamenco.cs 10010 C 32 0 1 # 3 mambo.cs 10002 C 32 0 1 # 4 lambada.cs 10002 C 32 0 1 # 5 lambada.cs 10002 C 32 0 1 |