Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Future.cpp

Go to the documentation of this file.
00001 // $Id: Future.cpp,v 1.1.1.4 2003/02/21 18:36:32 chad Exp $
00002 
00003 #ifndef ACE_FUTURE_CPP
00004 #define ACE_FUTURE_CPP
00005 
00006 #include "ace/Future.h"
00007 
00008 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00009 # pragma once
00010 #endif /* ACE_LACKS_PRAGMA_ONCE */
00011 
00012 ACE_RCSID (ace, Future, "$Id: Future.cpp,v 1.1.1.4 2003/02/21 18:36:32 chad Exp $")
00013 
00014 #if defined (ACE_HAS_THREADS)
00015 
00016 template <class T>
00017 ACE_Future_Holder<T>::ACE_Future_Holder (void)
00018 {
00019 }
00020 
00021 template <class T>
00022 ACE_Future_Holder<T>::ACE_Future_Holder (const ACE_Future<T> &item)
00023   : item_ (item)
00024 {
00025 }
00026 
00027 template <class T>
00028 ACE_Future_Holder<T>::~ACE_Future_Holder (void)
00029 {
00030 }
00031 
00032 template <class T>
00033 ACE_Future_Observer<T>::ACE_Future_Observer (void)
00034 {
00035 }
00036 
00037 template <class T>
00038 ACE_Future_Observer<T>::~ACE_Future_Observer (void)
00039 {
00040 }
00041 
00042 // Dump the state of an object.
00043 
00044 template <class T> void
00045 ACE_Future_Rep<T>::dump (void) const
00046 {
00047   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00048   ACE_DEBUG ((LM_DEBUG,
00049               "ref_count_ = %d\n",
00050  (int) this->ref_count_));
00051   ACE_DEBUG ((LM_INFO,"value_: \n"));
00052   if (this->value_)
00053     ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" (NON-NULL)\n")));
00054   else
00055     ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" (NULL)\n")));
00056 
00057   ACE_DEBUG ((LM_INFO,"value_ready_: \n"));
00058   this->value_ready_.dump ();
00059   ACE_DEBUG ((LM_INFO,"value_ready_mutex_: \n"));
00060   this->value_ready_mutex_.dump ();
00061   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00062 }
00063 
00064 template <class T> ACE_Future_Rep<T> *
00065 ACE_Future_Rep<T>::internal_create (void)
00066 {
00067   ACE_Future_Rep<T> *temp = 0;
00068   ACE_NEW_RETURN (temp,
00069                   ACE_Future_Rep<T> (),
00070                   0);
00071   return temp;
00072 }
00073 
00074 template <class T> ACE_Future_Rep<T> *
00075 ACE_Future_Rep<T>::create (void)
00076 {
00077   // Yes set ref count to zero.
00078   ACE_Future_Rep<T> *temp = internal_create ();
00079 #if defined (ACE_NEW_THROWS_EXCEPTIONS)
00080   if (temp == 0)
00081     ACE_throw_bad_alloc;
00082 #else
00083   ACE_ASSERT (temp != 0);
00084 #endif /* ACE_NEW_THROWS_EXCEPTIONS */
00085    return temp;
00086  }
00087 
00088 
00089 template <class T> ACE_Future_Rep<T> *
00090 ACE_Future_Rep<T>::attach (ACE_Future_Rep<T>*& rep)
00091 {
00092   ACE_ASSERT (rep != 0);
00093   // Use value_ready_mutex_ for both condition and ref count management
00094   ACE_MT (ACE_Guard<ACE_Thread_Mutex> r_mon (rep->value_ready_mutex_));
00095   ++rep->ref_count_;
00096   return rep;
00097 }
00098 
00099 template <class T> void
00100 ACE_Future_Rep<T>::detach (ACE_Future_Rep<T>*& rep)
00101 {
00102   ACE_ASSERT (rep != 0);
00103   // Use value_ready_mutex_ for both condition and ref count management
00104   ACE_MT (ACE_GUARD (ACE_Thread_Mutex, r_mon, rep->value_ready_mutex_));
00105 
00106   if (rep->ref_count_-- == 0)
00107     {
00108       ACE_MT (r_mon.release ());
00109       // We do not need the lock when deleting the representation.
00110       // There should be no side effects from deleting rep and we don
00111       // not want to release a deleted mutex.
00112       delete rep;
00113     }
00114 }
00115 
00116 template <class T> void
00117 ACE_Future_Rep<T>::assign (ACE_Future_Rep<T>*& rep, ACE_Future_Rep<T>* new_rep)
00118 {
00119   ACE_ASSERT (rep != 0);
00120   ACE_ASSERT (new_rep != 0);
00121   // Use value_ready_mutex_ for both condition and ref count management
00122   ACE_MT (ACE_GUARD (ACE_Thread_Mutex, r_mon, rep->value_ready_mutex_));
00123 
00124   ACE_Future_Rep<T>* old = rep;
00125   rep = new_rep;
00126 
00127   // detached old last for exception safety
00128   if (old->ref_count_-- == 0)
00129     {
00130       ACE_MT (r_mon.release ());
00131       // We do not need the lock when deleting the representation.
00132       // There should be no side effects from deleting rep and we don
00133       // not want to release a deleted mutex.
00134       delete old;
00135     }
00136 }
00137 
00138 template <class T>
00139 ACE_Future_Rep<T>::ACE_Future_Rep (void)
00140   : value_ (0),
00141     ref_count_ (0),
00142     value_ready_ (this->value_ready_mutex_)
00143 {
00144 }
00145 
00146 template <class T>
00147 ACE_Future_Rep<T>::~ACE_Future_Rep (void)
00148 {
00149   delete this->value_;
00150 }
00151 
00152 template <class T> int
00153 ACE_Future_Rep<T>::ready (void) const
00154 {
00155   return this->value_ != 0;
00156 }
00157 
00158 template <class T> int
00159 ACE_Future_Rep<T>::set (const T &r,
00160                         ACE_Future<T> &caller)
00161 {
00162   // If the value is already produced, ignore it...
00163   if (this->value_ == 0)
00164     {
00165       ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex,
00166                                 ace_mon,
00167                                 this->value_ready_mutex_,
00168                                 -1));
00169       // Otherwise, create a new result value.  Note the use of the
00170       // Double-checked locking pattern to avoid multiple allocations.
00171 
00172       if (this->value_ == 0)       // Still no value, so proceed
00173         {
00174           ACE_NEW_RETURN (this->value_,
00175                           T (r),
00176                           -1);
00177 
00178           // Remove and notify all subscribed observers.
00179           ACE_TYPENAME OBSERVER_COLLECTION::iterator iterator =
00180             this->observer_collection_.begin ();
00181 
00182           ACE_TYPENAME OBSERVER_COLLECTION::iterator end =
00183             this->observer_collection_.end ();
00184 
00185           while (iterator != end)
00186             {
00187               OBSERVER *observer = *iterator++;
00188               observer->update (caller);
00189             }
00190 
00191           // Signal all the waiting threads.
00192           return this->value_ready_.broadcast ();
00193         }
00194       // Destructor releases the lock.
00195     }
00196   return 0;
00197 }
00198 
00199 template <class T> int
00200 ACE_Future_Rep<T>::get (T &value,
00201                         ACE_Time_Value *tv) const
00202 {
00203   // If the value is already produced, return it.
00204   if (this->value_ == 0)
00205     {
00206       ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon,
00207                                 ACE_const_cast (ACE_Thread_Mutex &, this->value_ready_mutex_),
00208                                 -1));
00209       // If the value is not yet defined we must block until the
00210       // producer writes to it.
00211 
00212       while (this->value_ == 0)
00213         // Perform a timed wait.
00214         if ((ACE_const_cast (ACE_Condition_Thread_Mutex &, this->value_ready_)).wait (tv) == -1)
00215           return -1;
00216 
00217       // Destructor releases the lock.
00218     }
00219 
00220   value = *this->value_;
00221   return 0;
00222 }
00223 
00224 template <class T> int
00225 ACE_Future_Rep<T>::attach (ACE_Future_Observer<T> *observer,
00226                           ACE_Future<T> &caller)
00227 {
00228   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->value_ready_mutex_, -1));
00229 
00230   // Otherwise, create a new result value.  Note the use of the
00231   // Double-checked locking pattern to avoid corrupting the list.
00232 
00233   int result = 1;
00234 
00235   // If the value is already produced, then notify observer
00236   if (this->value_ == 0)
00237     result = this->observer_collection_.insert (observer);
00238   else
00239       observer->update (caller);
00240 
00241   return result;
00242 }
00243 
00244 template <class T> int
00245 ACE_Future_Rep<T>::detach (ACE_Future_Observer<T> *observer)
00246 {
00247   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->value_ready_mutex_, -1));
00248 
00249   // Remove all occurrences of the specified observer from this
00250   // objects hash map.
00251   return this->observer_collection_.remove (observer);
00252 }
00253 
00254 template <class T>
00255 ACE_Future_Rep<T>::operator T ()
00256 {
00257   // If the value is already produced, return it.
00258   if (this->value_ == 0)
00259     {
00260       // Constructor of ace_mon acquires the mutex.
00261       ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->value_ready_mutex_, 0));
00262 
00263       // If the value is not yet defined we must block until the
00264       // producer writes to it.
00265 
00266       // Wait ``forever.''
00267 
00268       while (this->value_ == 0)
00269         if (this->value_ready_.wait () == -1)
00270           // What to do in this case since we've got to indicate
00271           // failure somehow?  Exceptions would be nice, but they're
00272           // not portable...
00273           return 0;
00274 
00275       // Destructor releases the mutex
00276     }
00277 
00278   return *this->value_;
00279 }
00280 
00281 template <class T>
00282 ACE_Future<T>::ACE_Future (void)
00283   : future_rep_ (FUTURE_REP::create ())
00284 {
00285 }
00286 
00287 template <class T>
00288 ACE_Future<T>::ACE_Future (const ACE_Future<T> &r)
00289   : future_rep_ (FUTURE_REP::attach (((ACE_Future<T> &) r).future_rep_))
00290 {
00291 }
00292 
00293 template <class T>
00294 ACE_Future<T>::ACE_Future (const T &r)
00295   : future_rep_ (FUTURE_REP::create ())
00296 {
00297   ACE_DEBUG ((LM_DEBUG,
00298               ACE_LIB_TEXT (" (%t) funny constructor\n")));
00299   this->future_rep_->set (r,
00300                           *this);
00301 }
00302 
00303 template <class T>
00304 ACE_Future<T>::~ACE_Future (void)
00305 {
00306   FUTURE_REP::detach (future_rep_);
00307 }
00308 
00309 template <class T> int
00310 ACE_Future<T>::operator== (const ACE_Future<T> &r) const
00311 {
00312   return r.future_rep_ == this->future_rep_;
00313 }
00314 
00315 template <class T> int
00316 ACE_Future<T>::operator!= (const ACE_Future<T> &r) const
00317 {
00318   return r.future_rep_ != this->future_rep_;
00319 }
00320 
00321 template <class T> int
00322 ACE_Future<T>::cancel (const T &r)
00323 {
00324   this->cancel ();
00325   return this->future_rep_->set (r,
00326                                  *this);
00327 }
00328 
00329 template <class T> int
00330 ACE_Future<T>::cancel (void)
00331 {
00332   // If this ACE_Future is already attached to a ACE_Future_Rep,
00333   // detach it (maybe delete the ACE_Future_Rep).
00334   FUTURE_REP::assign (this->future_rep_,
00335                       FUTURE_REP::create ());
00336   return 0;
00337 }
00338 
00339 template <class T> int
00340 ACE_Future<T>::set (const T &r)
00341 {
00342   // Give the pointer to the result to the ACE_Future_Rep.
00343   return this->future_rep_->set (r,
00344                                  *this);
00345 }
00346 
00347 template <class T> int
00348 ACE_Future<T>::ready (void) const
00349 {
00350   // We're ready if the ACE_Future_rep is ready...
00351   return this->future_rep_->ready ();
00352 }
00353 
00354 template <class T> int
00355 ACE_Future<T>::get (T &value,
00356                     ACE_Time_Value *tv) const
00357 {
00358   // We return the ACE_Future_rep.
00359   return this->future_rep_->get (value, tv);
00360 }
00361 
00362 template <class T> int
00363 ACE_Future<T>::attach (ACE_Future_Observer<T> *observer)
00364 {
00365   return this->future_rep_->attach (observer, *this);
00366 }
00367 
00368 template <class T> int
00369 ACE_Future<T>::detach (ACE_Future_Observer<T> *observer)
00370 {
00371   return this->future_rep_->detach (observer);
00372 }
00373 
00374 template <class T>
00375 ACE_Future<T>::operator T ()
00376 {
00377   // note that this will fail (and COREDUMP!)
00378   // if future_rep_ == 0 !
00379   //
00380   // but...
00381   // this is impossible unless somebody is so stupid to
00382   // try something like this:
00383   //
00384   // Future<T> futT;
00385   // T t;
00386   // t = futT;
00387 
00388   // perform type conversion on Future_Rep.
00389   return *future_rep_;
00390 }
00391 
00392 template <class T> void
00393 ACE_Future<T>::operator = (const ACE_Future<T> &rhs)
00394 {
00395   // assignment:
00396   //
00397   //  bind <this> to the same <ACE_Future_Rep> as <r>.
00398 
00399   // This will work if &r == this, by first increasing the ref count
00400   ACE_Future<T> &r = (ACE_Future<T> &) rhs;
00401   FUTURE_REP::assign (this->future_rep_,
00402                       FUTURE_REP::attach (r.future_rep_));
00403 }
00404 
00405 template <class T> void
00406 ACE_Future<T>::dump (void) const
00407 {
00408   ACE_DEBUG ((LM_DEBUG,
00409               ACE_BEGIN_DUMP, this));
00410 
00411   if (this->future_rep_)
00412     this->future_rep_->dump ();
00413 
00414   ACE_DEBUG ((LM_DEBUG,
00415               ACE_END_DUMP));
00416 }
00417 
00418 template <class T> ACE_Future_Rep<T> *
00419 ACE_Future<T>::get_rep ()
00420 {
00421   return this->future_rep_;
00422 }
00423 
00424 template <class T> void *
00425 ACE_Future<T>::operator new (size_t)
00426 {
00427   ACE_throw_bad_alloc;
00428 #if defined (__HP_aCC)
00429   return 0;
00430 #endif /* 0 */
00431 }
00432 
00433 template <class T> void
00434 ACE_Future<T>::operator delete (void *)
00435 {
00436 }
00437 
00438 template <class T> void
00439 ACE_Future<T>::operator & ()
00440 {
00441 }
00442 
00443 #endif /* ACE_HAS_THREADS */
00444 #endif /* ACE_FUTURE_CPP */

Generated on Mon Jun 16 11:19:44 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002