Future.cpp

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

Generated on Tue Feb 2 17:18:39 2010 for ACE by  doxygen 1.4.7