Future.cpp

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

Generated on Thu Nov 9 09:41:51 2006 for ACE by doxygen 1.3.6