Timer_List_T.cpp

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

Generated on Thu Nov 9 09:42:07 2006 for ACE by doxygen 1.3.6