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

Timer_List_T.cpp

Go to the documentation of this file.
00001 // $Id: Timer_List_T.cpp,v 1.1.1.4 2003/02/21 18:36:32 chad Exp $
00002 
00003 #ifndef ACE_TIMER_LIST_T_C
00004 #define ACE_TIMER_LIST_T_C
00005 
00006 #include "ace/Timer_List_T.h"
00007 #include "ace/Log_Msg.h"
00008 
00009 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00010 # pragma once
00011 #endif /* ACE_LACKS_PRAGMA_ONCE */
00012 
00013 ACE_RCSID(ace, Timer_List_T, "$Id: Timer_List_T.cpp,v 1.1.1.4 2003/02/21 18:36:32 chad Exp $")
00014 
00015 // Default Constructor
00016 
00017 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00018 ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_List_Iterator_T (List& lst)
00019   : list_ (lst)
00020 {
00021   this->first();
00022 }
00023 
00024 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00025 ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_List_Iterator_T (void)
00026 {
00027 }
00028 
00029 // Positions the iterator at the node right after the dummy node
00030 
00031 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00032 ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::first (void)
00033 {
00034   this->current_node_ = this->list_.get_first();
00035 }
00036 
00037 // Positions the iterator at the next node in the Timer Queue
00038 
00039 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00040 ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::next (void)
00041 {
00042   // Make sure that if we are at the end, we don't wrap around
00043   if (! this->isdone())
00044     this->current_node_ = this->current_node_->get_next ();
00045   if (this->current_node_  == this->list_.head_)
00046     this->current_node_ = 0;
00047 }
00048 
00049 // Returns true when we are at <head_>
00050 
00051 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00052 ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::isdone (void) const
00053 {
00054   return this->current_node_ == 0;
00055 }
00056 
00057 // Returns the node at <position_> or 0 if we are at the end
00058 
00059 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
00060 ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::item (void)
00061 {
00062   if (! this->isdone())
00063     return this->current_node_;
00064   return 0;
00065 }
00066 
00067 ///////////////////////////////////////////////////////////////////////////////
00068 ///////////////////////////////////////////////////////////////////////////////
00069 
00070 // Return our instance of the iterator
00071 
00072 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> &
00073 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::iter (void)
00074 {
00075   this->iterator_->first ();
00076   return *this->iterator_;
00077 }
00078 
00079 // Create an empty list.
00080 
00081 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00082 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_List_T (FUNCTOR* uf, FreeList* fl)
00083   : Base(uf, fl)
00084   , head_ (new ACE_Timer_Node_T<TYPE>)
00085   , id_counter_ (0)
00086 {
00087   ACE_TRACE ("ACE_Timer_List_T::ACE_Timer_List_T");
00088 
00089   this->head_->set_next (this->head_);
00090   this->head_->set_prev (this->head_);
00091 
00092   ACE_NEW (iterator_, Iterator(*this));
00093 }
00094 
00095 
00096 // Checks if list is empty.
00097 
00098 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00099 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::is_empty (void) const
00100 {
00101   ACE_TRACE ("ACE_Timer_List_T::is_empty");
00102   return this->get_first_i() == 0;
00103 }
00104 
00105 
00106 // Returns earliest time in a non-empty list.
00107 
00108 template <class TYPE, class FUNCTOR, class ACE_LOCK> const ACE_Time_Value &
00109 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::earliest_time (void) const
00110 {
00111   ACE_TRACE ("ACE_Timer_List_T::earliest_time");
00112   ACE_Timer_Node_T<TYPE>* first = this->get_first_i();
00113   if (first != 0)
00114     return first->get_timer_value ();
00115   return ACE_Time_Value::zero;
00116 }
00117 
00118 
00119 // Remove all remaining items in the list.
00120 
00121 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00122 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_List_T (void)
00123 {
00124   ACE_TRACE ("ACE_Timer_List_T::~ACE_Timer_List_T");
00125   ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_));
00126 
00127   delete iterator_;
00128 
00129   if (! this->is_empty()) {
00130     for (ACE_Timer_Node_T<TYPE>* n = this->get_first(); n != this->head_;) {
00131       ACE_Timer_Node_T<TYPE>* next = n->get_next();
00132       this->upcall_functor ().deletion (*this, n->get_type(), n->get_act());
00133       this->free_node(n);
00134       n = next;
00135     }
00136   }
00137 
00138   // delete the dummy node
00139   delete this->head_;
00140 }
00141 
00142 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00143 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const
00144 {
00145   ACE_TRACE ("ACE_Timer_List_T::dump");
00146   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00147 
00148   int count = 0;
00149 
00150   ACE_Timer_Node_T<TYPE>* n = this->get_first_i();
00151   if (n != 0) {
00152     for (; n != this->head_; n = n->get_next()) {
00153       count++;
00154     }
00155   }
00156 
00157   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nsize_ = %d"), count));
00158   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00159 }
00160 
00161 
00162 // Reschedule a periodic timer.  This function must be called with the
00163 // lock held.
00164 
00165 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00166 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::reschedule (ACE_Timer_Node_T<TYPE>* n)
00167 {
00168   ACE_TRACE ("ACE_Timer_List_T::reschedule");
00169   this->schedule_i(n, n->get_timer_value());
00170 }
00171 
00172 
00173 // Insert a new handler that expires at time future_time; if interval
00174 // is > 0, the handler will be reinvoked periodically.
00175 
00176 template <class TYPE, class FUNCTOR, class ACE_LOCK> long
00177 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::schedule (const TYPE &type,
00178                                                  const void *act,
00179                                                  const ACE_Time_Value &future_time,
00180                                                  const ACE_Time_Value &interval)
00181 {
00182   ACE_TRACE ("ACE_Timer_List_T::schedule");
00183   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00184 
00185   ACE_Timer_Node_T<TYPE>* n = this->alloc_node();
00186 
00187   if (n != 0)
00188   {
00189     long id = this->id_counter_++;
00190 
00191     if (id != -1) {
00192       n->set (type, act, future_time, interval, 0, 0, id);
00193       this->schedule_i (n, future_time);
00194     }
00195     return id;
00196   }
00197 
00198   // Failure return
00199   errno = ENOMEM;
00200   return -1;
00201 }
00202 
00203 /// The shared scheduling functionality between schedule() and reschedule()
00204 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00205 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (ACE_Timer_Node_T<TYPE>* n,
00206                                                         const ACE_Time_Value& expire)
00207 {
00208   if (this->is_empty()) {
00209     n->set_prev(this->head_);
00210     n->set_next(this->head_);
00211     this->head_->set_prev(n);
00212     this->head_->set_next(n);
00213     return;
00214   }
00215 
00216   // We always want to search backwards from the tail of the list, because
00217   // this minimizes the search in the extreme case when lots of timers are
00218   // scheduled for exactly the same time, and it also assumes that most of
00219   // the timers will be scheduled later than existing timers.
00220   ACE_Timer_Node_T<TYPE>* p = this->head_->get_prev();
00221   while (p != this->head_ && p->get_timer_value() > expire)
00222     p = p->get_prev();
00223 
00224   // insert after
00225   n->set_prev(p);
00226   n->set_next(p->get_next());
00227   p->get_next()->set_prev(n);
00228   p->set_next(n);
00229 }
00230 
00231 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00232 ACE_Timer_Node_T<TYPE>*
00233 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::find_node(long timer_id) const
00234 {
00235   ACE_Timer_Node_T<TYPE>* n = this->get_first_i();
00236   if (n == 0)
00237     return 0;
00238 
00239   for (; n != this->head_; n = n->get_next()) {
00240     if (n->get_timer_id() == timer_id) {
00241       return n;
00242     }
00243   }
00244   return 0;
00245 }
00246 
00247 // Locate and update the inteval on the timer_id
00248 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00249 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::reset_interval (long timer_id,
00250                                                            const ACE_Time_Value &interval)
00251 {
00252   ACE_TRACE ("ACE_Timer_List_T::reset_interval");
00253   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00254   ACE_Timer_Node_T<TYPE>* n = this->find_node(timer_id);
00255   if (n != 0) {
00256     n->set_interval(interval); // The interval will take effect the next time this node is expired.
00257     return 0;
00258   }
00259   return -1;
00260 }
00261 
00262 // Locate and remove the single <ACE_Event_Handler> with a value of
00263 // <timer_id> from the timer queue.
00264 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00265 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id,
00266                                                    const void **act,
00267                                                    int skip_close)
00268 {
00269   ACE_TRACE ("ACE_Timer_List_T::cancel");
00270   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00271   ACE_Timer_Node_T<TYPE>* n = this->find_node(timer_id);
00272   if (n != 0) {
00273     if (act != 0)
00274       *act = n->get_act();
00275     this->cancel_i(n, skip_close);
00276     return 1;
00277   }
00278   return 0;
00279 }
00280 
00281 // Locate and remove all values of <handler> from the timer queue.
00282 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00283 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE &type, int skip_close)
00284 {
00285   ACE_TRACE ("ACE_Timer_List_T::cancel");
00286   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00287 
00288   int num_canceled = 0; // Note : Technically this can overflow.
00289 
00290   if (! this->is_empty()) {
00291 
00292     for (ACE_Timer_Node_T<TYPE>* n = this->get_first(); n != this->head_;)
00293     {
00294       if (n->get_type() == type) // Note: Typically Type is an ACE_Event_Handler*
00295       {
00296         ++num_canceled;
00297 
00298         ACE_Timer_Node_T<TYPE>* tmp = n;
00299         n = n->get_next();
00300         int always_skip_close = 1; // todo : Is this correct?
00301         this->cancel_i(tmp, always_skip_close);
00302       }
00303       else
00304       {
00305         n = n->get_next();
00306       }
00307     }
00308 
00309   }
00310 
00311   if (! skip_close) { //  && num_canceled > 0) {
00312     this->upcall_functor().cancellation (*this, type);
00313   }
00314   return num_canceled;
00315 }
00316 
00317 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00318 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::unlink (ACE_Timer_Node_T<TYPE>* n)
00319 {
00320   n->get_prev()->set_next(n->get_next());
00321   n->get_next()->set_prev(n->get_prev());
00322   n->set_prev(0);
00323   n->set_next(0);
00324 }
00325 
00326 /// Shared subset of the two cancel() methods.
00327 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00328 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::cancel_i (ACE_Timer_Node_T<TYPE>* n, int skip_close)
00329 {
00330   this->unlink(n);
00331   this->free_node (n);
00332   if (! skip_close) {
00333     this->upcall_functor().cancellation (*this, n->get_type());
00334   }
00335 }
00336 
00337 // Reads the first node on the list and returns it.
00338 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
00339 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::get_first (void)
00340 {
00341   ACE_TRACE ("ACE_Timer_List_T::get_first");
00342   return this->get_first_i();
00343 }
00344 
00345 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
00346 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::get_first_i (void) const
00347 {
00348   ACE_TRACE ("ACE_Timer_List_T::get_first_i");
00349   ACE_Timer_Node_T<TYPE>* first = this->head_->get_next();
00350   if (first != this->head_) // Note : is_empty() uses get_first()
00351     return first;
00352   return 0;
00353 }
00354 
00355 
00356 // Removes the first node on the list and returns it.
00357 
00358 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
00359 ACE_Timer_List_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first (void)
00360 {
00361   ACE_TRACE ("ACE_Timer_List_T::remove_first");
00362   ACE_Timer_Node_T<TYPE>* first = this->get_first();
00363   if (first != 0) {
00364     this->unlink(first);
00365     return first;
00366   }
00367   return 0;
00368 }
00369 
00370 #endif /* ACE_TIMER_LIST_T_C */

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