Timer_Wheel_T.cpp

Go to the documentation of this file.
00001 // Timer_Wheel_T.cpp,v 1.68 2005/10/28 23:55:10 ossama Exp
00002 
00003 #ifndef ACE_TIMER_WHEEL_T_CPP
00004 #define ACE_TIMER_WHEEL_T_CPP
00005 
00006 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00007 # pragma once
00008 #endif /* ACE_LACKS_PRAGMA_ONCE */
00009 
00010 #include "ace/OS_NS_sys_time.h"
00011 #include "ace/Guard_T.h"
00012 #include "ace/Timer_Wheel_T.h"
00013 #include "ace/Log_Msg.h"
00014 
00015 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00016 
00017 // Design/implementation notes for ACE_Timer_Wheel_T.
00018 //
00019 // Each timer queue entry is represented by a ACE_Timer_Node.
00020 // The timing wheel is divided into a number of "spokes"; there are
00021 // spoke_count_ spokes in the wheel. Each timer is hashed into one of the
00022 // spokes. Entries within each spoke are linked in a double-linked list
00023 // in order of increasing expiration. The first ACE_Timer_Node in each
00024 // spoke is a "dummy node" that marks the end of the list of ACE_Timer_Nodes
00025 // in that spoke.
00026 //
00027 // The timer ID for a scheduled timer is formed by its spoke position in
00028 // the wheel, and the number of timers that have been inserted in that spoke
00029 // since the queue was initialized. N bits of the long timer_id are used
00030 // to determine the spoke, and M bits are used as a counter.
00031 // Each time a Node is inserted into a spoke, it's counter
00032 // is incremented. The count is kept in the timer ID field
00033 // of the dummy root Node. In the event of overflow of the counter, the spoke
00034 // must be searched for each new id to make sure it's not already in use. To
00035 // prevent having to do an exhaustive search each time, we keep extra data
00036 // in the dummy root Node.
00037 /**
00038 * Default Constructor that sets defaults for spoke_count_ and resolution_
00039 * and doesn't do any preallocation.
00040 *
00041 * @param upcall_functor A pointer to a functor to use instead of the default
00042 * @param freelist       A pointer to a freelist to use instead of the default
00043 */
00044 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00045 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Wheel_T
00046 (FUNCTOR* upcall_functor
00047  , FreeList* freelist
00048  )
00049 : Base (upcall_functor, freelist)
00050 , spokes_(0)
00051 , spoke_count_(0) // calculated in open_i
00052 , spoke_bits_(0)
00053 , res_bits_ (0)
00054 , earliest_spoke_ (0)
00055 , iterator_(0)
00056 , timer_count_(0)
00057 {
00058   ACE_TRACE ("ACE_Timer_Wheel_T::ACE_Timer_Wheel_T");
00059   this->open_i (0,
00060                 ACE_DEFAULT_TIMER_WHEEL_SIZE,
00061                 ACE_DEFAULT_TIMER_WHEEL_RESOLUTION);
00062 }
00063 
00064 /**
00065 * Constructor that sets up the timing wheel and also may preallocate
00066 * some nodes on the free list
00067 *
00068 * @param spoke_count    The number of lists in the timer wheel
00069 * @param resolution     The time resolution in milliseconds used by the hashing function
00070 * @param prealloc       The number of entries to prealloc in the free_list
00071 * @param upcall_functor A pointer to a functor to use instead of the default
00072 * @param freelist       A pointer to a freelist to use instead of the default
00073 */
00074 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00075 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Wheel_T
00076   (u_int spoke_count,
00077    u_int resolution,
00078    size_t prealloc,
00079    FUNCTOR* upcall_functor,
00080    FreeList* freelist)
00081 : Base (upcall_functor, freelist)
00082 , spokes_ (0)
00083 , spoke_count_ (0) // calculated in open_i
00084 , spoke_bits_ (0)
00085 , res_bits_ (0)
00086 , earliest_spoke_ (0)
00087 , iterator_ (0)
00088 , timer_count_ (0)
00089 {
00090   ACE_TRACE ("ACE_Timer_Wheel_T::ACE_Timer_Wheel_T");
00091   this->open_i (prealloc, spoke_count, resolution);
00092 }
00093 
00094 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00095 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::power2bits (int n,
00096                                                         int min_bits,
00097                                                         int max_bits)
00098 {
00099   int max = (1 << max_bits) - 1;
00100   if (n > max)
00101     return max_bits;
00102 
00103   // count the bits in n.
00104   int i = 0;
00105   int tmp = n;
00106   do
00107     {
00108       tmp >>= 1;
00109       ++i;
00110     }
00111   while (tmp != 0);
00112 
00113   if (i <= min_bits)
00114     return min_bits;
00115 
00116   // Which is nearest?
00117   int a = (1 << i) - n;
00118   int b = (1 << (i - 1)) - n;
00119   if (b < 0)
00120     b = -b;
00121   if (b < a)
00122     return i - 1;
00123   return i;
00124 }
00125 
00126 /**
00127 * Initialize the queue. Uses the established members for all needed
00128 * information.
00129 */
00130 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00131 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::open_i
00132   (size_t prealloc, u_int spokes, u_int res)
00133 {
00134   ACE_TRACE ("ACE_Timer_Wheel_T::open_i");
00135 
00136   this->gettimeofday (ACE_OS::gettimeofday);
00137 
00138   // Rather than waste bits in our timer id, we might as well round up
00139   // the spoke count to the next power of two - 1 . (i.e 1,3,7,15,...127,etc.)
00140   const int MIN_SPOKE_BITS = 3;  // Allow between 8 and 4096 spokes
00141   const int MAX_SPOKE_BITS = 12;
00142   const int MAX_RES_BITS = 20;   // 20 is plenty, even on 64 bit platforms.
00143 
00144   this->spoke_bits_ = power2bits (spokes, MIN_SPOKE_BITS, MAX_SPOKE_BITS);
00145   this->res_bits_ = power2bits (res, 1, MAX_RES_BITS);
00146 
00147   this->spoke_count_ = 1 << this->spoke_bits_;
00148 
00149   this->free_list_->resize (prealloc + this->spoke_count_);
00150 
00151   this->wheel_time_.msec (1 << (this->res_bits_ + this->spoke_bits_));
00152 
00153   ACE_NEW (this->spokes_, ACE_Timer_Node_T<TYPE>* [this->spoke_count_]);
00154 
00155   // Create the root nodes. These will be treated specially
00156   for (u_int i = 0; i < this->spoke_count_; ++i)
00157   {
00158     ACE_Timer_Node_T<TYPE>* root = this->alloc_node ();
00159     root->set (0, 0, ACE_Time_Value::zero, ACE_Time_Value::zero, root, root, 0);
00160     this->spokes_[i] = root;
00161   }
00162 
00163   ACE_NEW (iterator_, Iterator (*this));
00164 }
00165 
00166 /// Destructor just cleans up its memory
00167 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00168 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Wheel_T (void)
00169 {
00170   ACE_TRACE ("ACE_Timer_Wheel_T::~ACE_Timer_Wheel_T");
00171 
00172   delete iterator_;
00173 
00174   for (u_int i = 0; i < this->spoke_count_; ++i)
00175   {
00176     // Free all the nodes starting at the root
00177     ACE_Timer_Node_T<TYPE>* root = this->spokes_[i];
00178     for (ACE_Timer_Node_T<TYPE>* n = root->get_next (); n != root;)
00179     {
00180       ACE_Timer_Node_T<TYPE>* next = n->get_next ();
00181       this->upcall_functor ().deletion (*this,
00182                                         n->get_type (),
00183                                         n->get_act ());
00184       this->free_node (n);
00185       n = next;
00186     }
00187     delete root;
00188   }
00189   delete[] this->spokes_;
00190 }
00191 
00192 /// Searches for a node by timer_id within one spoke.
00193 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00194 ACE_Timer_Node_T<TYPE>*
00195 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::find_spoke_node
00196   (u_int spoke, long timer_id) const
00197 {
00198   ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
00199   for (ACE_Timer_Node_T<TYPE>* n = root->get_next ();
00200        n != root;
00201        n = n->get_next ())
00202     {
00203       if (n->get_timer_id () == timer_id)
00204         return n;
00205     }
00206   return 0;
00207 }
00208 
00209 /// Searches all spokes for a node matching the specified timer_id
00210 /// Uses the spoke encoded in the timer_id as a starting place.
00211 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00212 ACE_Timer_Node_T<TYPE>*
00213 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::find_node (long timer_id) const
00214 {
00215   if (timer_id == -1)
00216     return 0;
00217 
00218   // Search the spoke where timer_id was originally scheduled
00219   u_int spoke_mask = this->spoke_count_ - 1;
00220   u_int start = timer_id & spoke_mask;
00221   ACE_Timer_Node_T<TYPE>* n = this->find_spoke_node (start, timer_id);
00222   if (n != 0)
00223     return n;
00224 
00225   //ACE_ERROR((LM_ERROR, "Node not found in original spoke.\n"));
00226 
00227   // Search the rest of the spokes
00228   for (u_int i = 0; i < this->spoke_count_; ++i)
00229     {
00230       if (i != start)
00231         { // already searched this one
00232           n = this->find_spoke_node (i, timer_id);
00233           if (n != 0)
00234             return n;
00235         }
00236     }
00237 
00238   //ACE_ERROR((LM_ERROR, "Node not found.\n"));
00239   return 0;
00240 }
00241 
00242 /**
00243 * Check to see if the wheel is empty
00244 *
00245 * @return True if empty
00246 */
00247 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00248 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::is_empty (void) const
00249 {
00250   ACE_TRACE ("ACE_Timer_Wheel_T::is_empty");
00251   return timer_count_ == 0;
00252 }
00253 
00254 
00255 /**
00256 * @return First (earliest) node in the wheel_'s earliest_spoke_ list
00257 */
00258 template <class TYPE, class FUNCTOR, class ACE_LOCK> const ACE_Time_Value &
00259 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::earliest_time (void) const
00260 {
00261   ACE_TRACE ("ACE_Timer_Wheel_T::earliest_time");
00262   ACE_Timer_Node_T<TYPE>* n = this->get_first_i ();
00263   if (n != 0)
00264     return n->get_timer_value ();
00265   return ACE_Time_Value::zero;
00266 }
00267 
00268 /// Uses a simple hash to find which spoke to use based on when the
00269 /// timer is due to expire. Hopefully the 64bit int operations avoid
00270 /// any overflow problems.
00271 template <class TYPE, class FUNCTOR, class ACE_LOCK> u_int
00272 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::calculate_spoke
00273   (const ACE_Time_Value& t) const
00274 {
00275   return static_cast<u_int> ((t.msec () >> this->res_bits_) & (this->spoke_count_ - 1));
00276 }
00277 
00278 /// Generates a unique timer_id for the given spoke. It should be pretty
00279 /// fast until the point where the counter overflows.  At that time you
00280 /// have to do exhaustive searches within the spoke to ensure that a particular
00281 /// timer id is not already in use. Some optimizations are in place so
00282 /// that this hopefully doesn't have to happen often.
00283 template <class TYPE, class FUNCTOR, class ACE_LOCK> long
00284 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::generate_timer_id (u_int spoke)
00285 {
00286 
00287   int cnt_bits = sizeof (long) * 8 - this->spoke_bits_;
00288   long max_cnt = ((long)1 << cnt_bits) - 1;
00289   if (spoke == this->spoke_count_)
00290     --max_cnt; // Because -1 is used as a special invalid timer_id.
00291 
00292   ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
00293 
00294   if (root == root->get_next ())
00295     root->set_act(0);
00296 
00297   // We use this field to keep track of the next counter value that
00298   // may be in use. Of course it may have expired, so we just use
00299   // this field so that we know when we don't have to check for duplicates
00300 #if defined (ACE_WIN64)
00301   // The cast below is legit... we know that long is shorter than a
00302   // pointer, but are only using it as a 'long' storage area.
00303 #  pragma warning(push)
00304 #  pragma warning(disable : 4311)
00305 #endif /* ACE_WIN64 */
00306   long next_cnt = reinterpret_cast<long> (root->get_act ());
00307 #if defined (ACE_WIN64)
00308 #  pragma warning(pop)
00309 #endif /* ACE_WIN64 */
00310 
00311   // This field is used as a counter instead of a timer_id.
00312   long cnt = root->get_timer_id ();
00313 
00314   if (cnt >= max_cnt && root == root->get_next ())
00315     {
00316       // Special case when we overflow on an empty spoke. We can just
00317       // wrap the count around without searching for duplicates. We only
00318       // want to do this when the counter overflows, so that we return
00319       // unique timer_id values as often as possible.
00320       root->set_timer_id (1);
00321       return spoke;
00322     }
00323   else if (cnt >= max_cnt)
00324     { // overflow
00325       cnt = 0; // try again starting at zero
00326     }
00327   else if (next_cnt == 0 || cnt < next_cnt)
00328     {
00329       root->set_timer_id (cnt + 1);
00330       return (cnt << this->spoke_bits_) | spoke;
00331     }
00332 
00333   //ACE_ERROR((LM_ERROR, "Timer id overflow. We have to search now.\n"));
00334 
00335   // We've run out of consecutive id numbers so now we have to search
00336   // for a unique id.
00337   // We'll try increasing numbers until we find one that is not in use,
00338   // and we'll record the next highest number so that we can avoid this
00339   // search as often as possible.
00340   for (; cnt < max_cnt - 1; ++cnt)
00341     {
00342       long id = (cnt << this->spoke_bits_) | spoke;
00343       ACE_Timer_Node_T<TYPE>* n = this->find_spoke_node (spoke, id);
00344       if (n == 0)
00345         {
00346           root->set_timer_id (cnt + 1);
00347           // Now we need to find the next highest cnt in use
00348           next_cnt = 0;
00349           for (; n != root; n = n->get_next ())
00350             {
00351               long tmp = n->get_timer_id () >> this->spoke_bits_;
00352               if (tmp > cnt && (tmp < next_cnt || next_cnt == 0))
00353                 next_cnt = tmp;
00354             }
00355 #if defined (ACE_WIN64)
00356           // The cast below is legit... we know we're storing a long in
00357           // a pointer, but are only using it as a 'long' storage area.
00358 #  pragma warning(push)
00359 #  pragma warning(disable : 4312)
00360 #endif /* ACE_WIN64 */
00361           root->set_act (reinterpret_cast<void*> (next_cnt));
00362 #if defined (ACE_WIN64)
00363 #  pragma warning(pop)
00364 #endif /* ACE_WIN64 */
00365           return id;
00366         }
00367     }
00368 
00369   return -1; // We did our best, but the spoke is full.
00370 }
00371 
00372 /**
00373 * Creates a ACE_Timer_Node_T based on the input parameters.  Then inserts
00374 * the node into the wheel using reschedule ().  Then returns a timer_id.
00375 *
00376 *  @param type            The data of the timer node
00377 *  @param act             Asynchronous Completion Token (AKA magic cookie)
00378 *  @param future_time     The time the timer is scheduled for (absolute time)
00379 *  @param interval        If not ACE_Time_Value::zero, then this is a periodic
00380 *                         timer and interval is the time period
00381 *
00382 *  @return Unique identifier (can be used to cancel the timer).
00383 *          -1 on failure.
00384 */
00385 template <class TYPE, class FUNCTOR, class ACE_LOCK> long
00386 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (const TYPE& type,
00387                                                         const void* act,
00388                                                         const ACE_Time_Value& future_time,
00389                                                         const ACE_Time_Value& interval)
00390 {
00391   ACE_TRACE ("ACE_Timer_Wheel_T::schedule_i");
00392 
00393   ACE_Timer_Node_T<TYPE>* n = this->alloc_node ();
00394 
00395   if (n != 0)
00396     {
00397       u_int spoke = calculate_spoke (future_time);
00398       long id = generate_timer_id (spoke);
00399 
00400       //ACE_ERROR((LM_ERROR, "Scheduling %x spoke:%d id:%d\n", (long) n, spoke, id));
00401 
00402       if (id != -1)
00403         {
00404           n->set (type, act, future_time, interval, 0, 0, id);
00405           this->schedule_i (n, spoke, future_time);
00406         }
00407       return id;
00408     }
00409 
00410   // Failure return
00411   errno = ENOMEM;
00412   return -1;
00413 }
00414 
00415 /**
00416 * Takes an ACE_Timer_Node and inserts it into the correct position in
00417 * the correct list.  Also makes sure to update the earliest time.
00418 *
00419 * @param n The timer node to reschedule
00420 */
00421 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00422 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::reschedule (ACE_Timer_Node_T<TYPE>* n)
00423 {
00424   ACE_TRACE ("ACE_Timer_Wheel_T::reschedule");
00425   const ACE_Time_Value& expire = n->get_timer_value ();
00426   u_int spoke = calculate_spoke (expire);
00427   this->schedule_i (n, spoke, expire);
00428 }
00429 
00430 /// The shared scheduling functionality between schedule() and reschedule()
00431 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00432 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i
00433   (ACE_Timer_Node_T<TYPE>* n,
00434    u_int spoke,
00435    const ACE_Time_Value& expire)
00436 {
00437   // See if we need to update the earliest time
00438   if (this->is_empty() || expire < this->earliest_time ())
00439     this->earliest_spoke_ = spoke;
00440 
00441   ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
00442   ACE_Timer_Node_T<TYPE>* last = root->get_prev ();
00443 
00444   ++timer_count_;
00445 
00446   // If the spoke is empty
00447   if (last == root) {
00448     n->set_prev (root);
00449     n->set_next (root);
00450     root->set_prev (n);
00451     root->set_next (n);
00452     return;
00453   }
00454 
00455   // We always want to search backwards from the tail of the list, because
00456   // this minimizes the search in the extreme case when lots of timers are
00457   // scheduled for exactly the same time
00458   ACE_Timer_Node_T<TYPE>* p = root->get_prev ();
00459   while (p != root && p->get_timer_value () > expire)
00460     p = p->get_prev ();
00461 
00462   // insert after
00463   n->set_prev (p);
00464   n->set_next (p->get_next ());
00465   p->get_next ()->set_prev (n);
00466   p->set_next (n);
00467 }
00468 
00469 
00470 /**
00471 * Find the timer node by using the id as a pointer.  Then use set_interval()
00472 * on the node to update the interval.
00473 *
00474 * @param timer_id The timer identifier
00475 * @param interval The new interval
00476 *
00477 * @return 0 if successful, -1 if no.
00478 */
00479 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00480 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::reset_interval (long timer_id,
00481                                                             const ACE_Time_Value &interval
00482                                                             )
00483 {
00484   ACE_TRACE ("ACE_Timer_Wheel_T::reset_interval");
00485   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00486   ACE_Timer_Node_T<TYPE>* n = this->find_node (timer_id);
00487   if (n != 0)
00488     {
00489       // The interval will take effect the next time this node is expired.
00490       n->set_interval (interval);
00491       return 0;
00492     }
00493   return -1;
00494 }
00495 
00496 
00497 /**
00498 * Goes through every list in the wheel and whenever we find one with the
00499 * correct type value, we remove it and continue.  At the end make sure
00500 * we reset the earliest time value in case the earliest timers were
00501 * removed.
00502 *
00503 * @param type       The value to search for.
00504 * @param skip_close If this non-zero, the cancellation method of the
00505 *                   functor will not be called for each cancelled timer.
00506 *
00507 * @return Number of timers cancelled
00508 */
00509 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00510 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE& type, int skip_close)
00511 {
00512   ACE_TRACE ("ACE_Timer_Wheel_T::cancel");
00513   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00514 
00515   int num_canceled = 0; // Note : Technically this can overflow.
00516 
00517   if (!this->is_empty ())
00518     {
00519       ACE_Timer_Node_T<TYPE>* first = this->get_first ();
00520       ACE_Time_Value last = first->get_timer_value ();
00521       int recalc = 0;
00522 
00523       for (u_int i = 0; i < this->spoke_count_; ++i)
00524         {
00525           ACE_Timer_Node_T<TYPE>* root = this->spokes_[i];
00526           for (ACE_Timer_Node_T<TYPE>* n = root->get_next (); n != root; )
00527             {
00528               if (n->get_type () == type)
00529                 {
00530                   ++num_canceled;
00531                   if (n == first)
00532                     recalc = 1;
00533 
00534                   ACE_Timer_Node_T<TYPE>* tmp = n;
00535                   n = n->get_next ();
00536 
00537                   this->cancel_i (tmp);
00538                 }
00539               else
00540                 {
00541                   n = n->get_next ();
00542                 }
00543             }
00544         }
00545 
00546       if (recalc)
00547         this->recalc_earliest (last);
00548     }
00549 
00550   // Call the close hooks.
00551   int cookie = 0;
00552 
00553   // cancel_type() called once per <type>.
00554   this->upcall_functor ().cancel_type (*this,
00555                                        type,
00556                                        skip_close,
00557                                        cookie);
00558 
00559   for (int i = 0;
00560        i < num_canceled;
00561        ++i)
00562     {
00563       // cancel_timer() called once per <timer>.
00564       this->upcall_functor ().cancel_timer (*this,
00565                                             type,
00566                                             skip_close,
00567                                             cookie);
00568     }
00569 
00570   return num_canceled;
00571 }
00572 
00573 
00574 /**
00575 * Cancels the single timer that is specified by the timer_id.  In this
00576 * case the timer_id is actually a pointer to the node, so we cast it
00577 * to the node.  This can be dangerous if the timer_id is made up
00578 * (or deleted twice) so we do a little sanity check.  Finally we update
00579 * the earliest time in case the earliest timer was removed.
00580 *
00581 * @param timer_id   Timer Identifier
00582 * @param act        Asychronous Completion Token (AKA magic cookie):
00583 *                   If this is non-zero, stores the magic cookie of
00584 *                   the cancelled timer here.
00585 * @param skip_close If this non-zero, the cancellation method of the
00586 *                   functor will not be called.
00587 *
00588 * @return 1 for sucess and 0 if the timer_id wasn't found (or was
00589 *         found to be invalid)
00590 */
00591 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00592 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id,
00593                                                     const void **act,
00594                                                     int skip_close)
00595 {
00596   ACE_TRACE ("ACE_Timer_Wheel_T::cancel");
00597   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00598   ACE_Timer_Node_T<TYPE>* n = this->find_node (timer_id);
00599   if (n != 0)
00600     {
00601       ACE_Time_Value last = n->get_timer_value ();
00602 
00603       int recalc = (this->get_first_i () == n);
00604 
00605       // Call the close hooks.
00606       int cookie = 0;
00607 
00608       // cancel_type() called once per <type>.
00609       this->upcall_functor ().cancel_type (*this,
00610                                            n->get_type (),
00611                                            skip_close,
00612                                            cookie);
00613 
00614       // cancel_timer() called once per <timer>.
00615       this->upcall_functor ().cancel_timer (*this,
00616                                             n->get_type (),
00617                                             skip_close,
00618                                             cookie);
00619       if (act != 0)
00620         *act = n->get_act ();
00621 
00622       this->cancel_i (n);
00623 
00624       if (recalc)
00625         this->recalc_earliest (last);
00626 
00627       return 1;
00628     }
00629   return 0;
00630 }
00631 
00632 /// Shared subset of the two cancel() methods.
00633 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00634 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel_i (ACE_Timer_Node_T<TYPE>* n)
00635 {
00636   this->unlink (n);
00637   this->free_node (n);
00638 }
00639 
00640 /// There are a few places where we have to figure out which timer
00641 /// will expire next. This method makes the assumption that spokes
00642 /// are always sorted, and that timers are always in the correct spoke
00643 /// determined from their expiration time.
00644 /// The last time is always passed in, even though you can often calculate
00645 /// it as get_first()->get_timer_value().
00646 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00647 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::recalc_earliest
00648   (const ACE_Time_Value& last)
00649 {
00650   // This is possible because we use a count for is_empty()
00651   if (this->is_empty ())
00652     return;
00653 
00654   ACE_Time_Value et = ACE_Time_Value::zero;
00655   u_int es = 0;
00656   u_int spoke = this->earliest_spoke_;
00657 
00658   // We will have to go around the wheel at most one time.
00659   for (u_int i = 0; i < this->spoke_count_; ++i)
00660     {
00661       ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
00662       ACE_Timer_Node_T<TYPE>* n = root->get_next ();
00663       if (n != root)
00664         {
00665           ACE_Time_Value t = n->get_timer_value ();
00666           if (t < last + this->wheel_time_)
00667             {
00668               this->earliest_spoke_ = spoke;
00669               return;
00670             }
00671           else if (et == ACE_Time_Value::zero || t < et)
00672             {
00673               et = t;
00674               es = spoke;
00675             }
00676         }
00677       if (++spoke >= this->spoke_count_)
00678         spoke = 0;
00679     }
00680 
00681   this->earliest_spoke_ = es;
00682   //ACE_ERROR((LM_ERROR, "We had to search the whole wheel.\n"));
00683 }
00684 
00685 /**
00686 * Dumps out the size of the wheel, the resolution, and the contents
00687 * of the wheel.
00688 */
00689 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00690 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const
00691 {
00692 #if defined (ACE_HAS_DUMP)
00693   ACE_TRACE ("ACE_Timer_Wheel_T::dump");
00694   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00695 
00696   ACE_DEBUG ((LM_DEBUG,
00697     ACE_LIB_TEXT ("\nspoke_count_ = %d"), this->spoke_count_));
00698   ACE_DEBUG ((LM_DEBUG,
00699     ACE_LIB_TEXT ("\nresolution_ = %d"), 1 << this->res_bits_));
00700   ACE_DEBUG ((LM_DEBUG,
00701     ACE_LIB_TEXT ("\nwheel_ = \n")));
00702 
00703   for (u_int i = 0; i < this->spoke_count_; ++i)
00704     {
00705       ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("%d\n"), i));
00706       ACE_Timer_Node_T<TYPE>* root = this->spokes_[i];
00707       for (ACE_Timer_Node_T<TYPE>* n = root->get_next ();
00708            n != root;
00709            n = n->get_next ())
00710         {
00711           n->dump ();
00712         }
00713     }
00714 
00715   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00716 #endif /* ACE_HAS_DUMP */
00717 }
00718 
00719 
00720 /**
00721 * Removes the earliest node and then find the new <earliest_spoke_>
00722 *
00723 * @return The earliest timer node.
00724 */
00725 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
00726 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first (void)
00727 {
00728   ACE_TRACE ("ACE_Timer_Wheel_T::remove_first");
00729   return remove_first_expired (ACE_Time_Value::max_time);
00730 }
00731 
00732 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00733 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::unlink (ACE_Timer_Node_T<TYPE>* n)
00734 {
00735   ACE_TRACE ("ACE_Timer_Wheel_T::unlink");
00736   --timer_count_;
00737   n->get_prev ()->set_next (n->get_next ());
00738   n->get_next ()->set_prev (n->get_prev ());
00739   n->set_prev (0);
00740   n->set_next (0);
00741 }
00742 
00743 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
00744 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first_expired (const ACE_Time_Value& now)
00745 {
00746   ACE_Timer_Node_T<TYPE>* n = this->get_first ();
00747   if (n != 0 && n->get_timer_value() <= now)
00748     {
00749       this->unlink (n);
00750       this->recalc_earliest (n->get_timer_value ());
00751       return n;
00752     }
00753   return 0;
00754 }
00755 
00756 /**
00757 * Returns the earliest node without removing it
00758 *
00759 * @return The earliest timer node.
00760 */
00761 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00762 ACE_Timer_Node_T<TYPE>*
00763 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first (void)
00764 {
00765   ACE_TRACE ("ACE_Timer_Wheel_T::get_first");
00766   return this->get_first_i ();
00767 }
00768 
00769 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00770 ACE_Timer_Node_T<TYPE>*
00771 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first_i (void) const
00772 {
00773   ACE_Timer_Node_T<TYPE>* root = this->spokes_[this->earliest_spoke_];
00774   ACE_Timer_Node_T<TYPE>* first = root->get_next ();
00775   if (first != root)
00776     return first;
00777   return 0;
00778 }
00779 
00780 
00781 /**
00782 * @return The iterator
00783 */
00784 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00785 ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>&
00786 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::iter (void)
00787 {
00788   this->iterator_->first ();
00789   return *this->iterator_;
00790 }
00791 
00792 /**
00793 * Dummy version of expire to get rid of warnings in Sun CC 4.2
00794 * Just call the expire of the base class.
00795 */
00796 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00797 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::expire ()
00798 {
00799   return ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::expire ();
00800 }
00801 
00802 /**
00803 * This is a specialized version of expire that is more suited for the
00804 * internal data representation.
00805 *
00806 * @param cur_time The time to expire timers up to.
00807 *
00808 * @return Number of timers expired
00809 */
00810 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00811 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value& cur_time)
00812 {
00813   ACE_TRACE ("ACE_Timer_Wheel_T::expire");
00814   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00815 
00816   int expcount = 0;
00817   ACE_Timer_Node_T<TYPE>* n = this->remove_first_expired (cur_time);
00818 
00819   while (n != 0)
00820     {
00821       ++expcount;
00822 
00823       //ACE_ERROR((LM_ERROR, "Expiring %x\n", (long) n));
00824 
00825       ACE_Timer_Node_Dispatch_Info_T<TYPE> info;
00826 
00827       // Get the dispatch info
00828       n->get_dispatch_info (info);
00829 
00830       if (n->get_interval () > ACE_Time_Value::zero)
00831         {
00832           // Make sure that we skip past values that have already
00833           // "expired".
00834           do
00835             n->set_timer_value (n->get_timer_value () +
00836                                 n->get_interval ());
00837           while (n->get_timer_value () <= cur_time);
00838 
00839           this->reschedule (n);
00840         }
00841       else
00842         {
00843           this->free_node (n);
00844         }
00845 
00846       const void *upcall_act = 0;
00847 
00848       this->preinvoke (info, cur_time, upcall_act);
00849 
00850       this->upcall (info, cur_time);
00851 
00852       this->postinvoke (info, cur_time, upcall_act);
00853 
00854       n = this->remove_first_expired (cur_time);
00855     }
00856 
00857   return expcount;
00858 }
00859 
00860 ///////////////////////////////////////////////////////////////////////////
00861 // ACE_Timer_Wheel_Iterator_T
00862 
00863 /**
00864 * Just initializes the iterator with a ACE_Timer_Wheel_T and then calls
00865 * first() to initialize the rest of itself.
00866 *
00867 * @param wheel A reference for a timer queue to iterate over
00868 */
00869 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00870 ACE_Timer_Wheel_Iterator_T<TYPE,FUNCTOR,ACE_LOCK>::ACE_Timer_Wheel_Iterator_T
00871 (Wheel& wheel)
00872 : timer_wheel_ (wheel)
00873 {
00874   this->first();
00875 }
00876 
00877 
00878 /**
00879 * Destructor, at this level does nothing.
00880 */
00881 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00882 ACE_Timer_Wheel_Iterator_T<TYPE,
00883 FUNCTOR,
00884 ACE_LOCK>::~ACE_Timer_Wheel_Iterator_T (void)
00885 {
00886 }
00887 
00888 
00889 /**
00890 * Positions the iterator at the first position in the timing wheel
00891 * that contains something. spoke_ will be set to the spoke position of
00892 * this entry and current_node_ will point to the first entry in that spoke.
00893 *
00894 * If the wheel is empty, spoke_ will be equal timer_wheel_.spoke_count_ and
00895 * current_node_ would be 0.
00896 */
00897 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00898 ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::first (void)
00899 {
00900   this->goto_next(0);
00901 }
00902 
00903 
00904 /**
00905 * Positions the iterator at the next node.
00906 */
00907 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00908 ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::next (void)
00909 {
00910   if (this->isdone())
00911     return;
00912 
00913   ACE_Timer_Node_T<TYPE>* n = this->current_node_->get_next ();
00914   ACE_Timer_Node_T<TYPE>* root = this->timer_wheel_.spokes_[this->spoke_];
00915   if (n == root)
00916     this->goto_next (this->spoke_ + 1);
00917   else
00918     this->current_node_ = n;
00919 }
00920 
00921 /// Helper class for common functionality of next() and first()
00922 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00923 ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::goto_next (u_int start_spoke)
00924 {
00925   // Find the first non-empty entry.
00926   u_int sc = this->timer_wheel_.spoke_count_;
00927   for (u_int i = start_spoke; i < sc; ++i)
00928   {
00929     ACE_Timer_Node_T<TYPE>* root = this->timer_wheel_.spokes_[i];
00930     ACE_Timer_Node_T<TYPE>* n = root->get_next ();
00931     if (n != root)
00932       {
00933         this->spoke_ = i;
00934         this->current_node_ = n;
00935         return;
00936       }
00937   }
00938   // empty
00939   this->spoke_ = sc;
00940   this->current_node_ = 0;
00941 }
00942 
00943 /**
00944 * @return True when we there aren't any more items (when current_node_ == 0)
00945 */
00946 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00947 ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::isdone (void) const
00948 {
00949   return this->current_node_ == 0;
00950 }
00951 
00952 /**
00953 * @return The node at the current spokeition in the sequence or 0 if the wheel
00954 *         is empty
00955 */
00956 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
00957 ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::item (void)
00958 {
00959   return this->current_node_;
00960 }
00961 
00962 ACE_END_VERSIONED_NAMESPACE_DECL
00963 
00964 #endif /* ACE_TIMER_WHEEL_T_CPP */

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