Timer_Wheel_T.cpp

Go to the documentation of this file.
00001 // $Id: Timer_Wheel_T.cpp 80826 2008-03-04 14:51:23Z wotte $
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> bool
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 
00514   int num_canceled = 0; // Note : Technically this can overflow.
00515   int cookie = 0;
00516 
00517   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00518 
00519   if (!this->is_empty ())
00520     {
00521       ACE_Timer_Node_T<TYPE>* first = this->get_first ();
00522       ACE_Time_Value last = first->get_timer_value ();
00523       int recalc = 0;
00524 
00525       for (u_int i = 0; i < this->spoke_count_; ++i)
00526         {
00527           ACE_Timer_Node_T<TYPE>* root = this->spokes_[i];
00528           for (ACE_Timer_Node_T<TYPE>* n = root->get_next (); n != root; )
00529             {
00530               if (n->get_type () == type)
00531                 {
00532                   ++num_canceled;
00533                   if (n == first)
00534                     recalc = 1;
00535 
00536                   ACE_Timer_Node_T<TYPE>* tmp = n;
00537                   n = n->get_next ();
00538 
00539                   this->cancel_i (tmp);
00540                 }
00541               else
00542                 {
00543                   n = n->get_next ();
00544                 }
00545             }
00546         }
00547 
00548       if (recalc)
00549         this->recalc_earliest (last);
00550     }
00551 
00552   // Call the close hooks.
00553 
00554   // cancel_type() called once per <type>.
00555   this->upcall_functor ().cancel_type (*this,
00556                                        type,
00557                                        skip_close,
00558                                        cookie);
00559 
00560   for (int i = 0;
00561        i < num_canceled;
00562        ++i)
00563     {
00564       // cancel_timer() called once per <timer>.
00565       this->upcall_functor ().cancel_timer (*this,
00566                                             type,
00567                                             skip_close,
00568                                             cookie);
00569     }
00570 
00571   return num_canceled;
00572 }
00573 
00574 
00575 /**
00576 * Cancels the single timer that is specified by the timer_id.  In this
00577 * case the timer_id is actually a pointer to the node, so we cast it
00578 * to the node.  This can be dangerous if the timer_id is made up
00579 * (or deleted twice) so we do a little sanity check.  Finally we update
00580 * the earliest time in case the earliest timer was removed.
00581 *
00582 * @param timer_id   Timer Identifier
00583 * @param act        Asychronous Completion Token (AKA magic cookie):
00584 *                   If this is non-zero, stores the magic cookie of
00585 *                   the cancelled timer here.
00586 * @param skip_close If this non-zero, the cancellation method of the
00587 *                   functor will not be called.
00588 *
00589 * @return 1 for sucess and 0 if the timer_id wasn't found (or was
00590 *         found to be invalid)
00591 */
00592 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00593 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id,
00594                                                     const void **act,
00595                                                     int skip_close)
00596 {
00597   ACE_TRACE ("ACE_Timer_Wheel_T::cancel");
00598   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00599   ACE_Timer_Node_T<TYPE>* n = this->find_node (timer_id);
00600   if (n != 0)
00601     {
00602       ACE_Time_Value last = n->get_timer_value ();
00603 
00604       int recalc = (this->get_first_i () == n);
00605 
00606       // Call the close hooks.
00607       int cookie = 0;
00608 
00609       // cancel_type() called once per <type>.
00610       this->upcall_functor ().cancel_type (*this,
00611                                            n->get_type (),
00612                                            skip_close,
00613                                            cookie);
00614 
00615       // cancel_timer() called once per <timer>.
00616       this->upcall_functor ().cancel_timer (*this,
00617                                             n->get_type (),
00618                                             skip_close,
00619                                             cookie);
00620       if (act != 0)
00621         *act = n->get_act ();
00622 
00623       this->cancel_i (n);
00624 
00625       if (recalc)
00626         this->recalc_earliest (last);
00627 
00628       return 1;
00629     }
00630   return 0;
00631 }
00632 
00633 /// Shared subset of the two cancel() methods.
00634 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00635 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel_i (ACE_Timer_Node_T<TYPE>* n)
00636 {
00637   this->unlink (n);
00638   this->free_node (n);
00639 }
00640 
00641 /// There are a few places where we have to figure out which timer
00642 /// will expire next. This method makes the assumption that spokes
00643 /// are always sorted, and that timers are always in the correct spoke
00644 /// determined from their expiration time.
00645 /// The last time is always passed in, even though you can often calculate
00646 /// it as get_first()->get_timer_value().
00647 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00648 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::recalc_earliest
00649   (const ACE_Time_Value& last)
00650 {
00651   // This is possible because we use a count for is_empty()
00652   if (this->is_empty ())
00653     return;
00654 
00655   ACE_Time_Value et = ACE_Time_Value::zero;
00656   u_int es = 0;
00657   u_int spoke = this->earliest_spoke_;
00658 
00659   // We will have to go around the wheel at most one time.
00660   for (u_int i = 0; i < this->spoke_count_; ++i)
00661     {
00662       ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
00663       ACE_Timer_Node_T<TYPE>* n = root->get_next ();
00664       if (n != root)
00665         {
00666           ACE_Time_Value t = n->get_timer_value ();
00667           if (t < last + this->wheel_time_)
00668             {
00669               this->earliest_spoke_ = spoke;
00670               return;
00671             }
00672           else if (et == ACE_Time_Value::zero || t < et)
00673             {
00674               et = t;
00675               es = spoke;
00676             }
00677         }
00678       if (++spoke >= this->spoke_count_)
00679         spoke = 0;
00680     }
00681 
00682   this->earliest_spoke_ = es;
00683   //ACE_ERROR((LM_ERROR, "We had to search the whole wheel.\n"));
00684 }
00685 
00686 /**
00687 * Dumps out the size of the wheel, the resolution, and the contents
00688 * of the wheel.
00689 */
00690 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00691 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const
00692 {
00693 #if defined (ACE_HAS_DUMP)
00694   ACE_TRACE ("ACE_Timer_Wheel_T::dump");
00695   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00696 
00697   ACE_DEBUG ((LM_DEBUG,
00698     ACE_TEXT ("\nspoke_count_ = %d"), this->spoke_count_));
00699   ACE_DEBUG ((LM_DEBUG,
00700     ACE_TEXT ("\nresolution_ = %d"), 1 << this->res_bits_));
00701   ACE_DEBUG ((LM_DEBUG,
00702     ACE_TEXT ("\nwheel_ = \n")));
00703 
00704   for (u_int i = 0; i < this->spoke_count_; ++i)
00705     {
00706       ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d\n"), i));
00707       ACE_Timer_Node_T<TYPE>* root = this->spokes_[i];
00708       for (ACE_Timer_Node_T<TYPE>* n = root->get_next ();
00709            n != root;
00710            n = n->get_next ())
00711         {
00712           n->dump ();
00713         }
00714     }
00715 
00716   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00717 #endif /* ACE_HAS_DUMP */
00718 }
00719 
00720 
00721 /**
00722 * Removes the earliest node and then find the new <earliest_spoke_>
00723 *
00724 * @return The earliest timer node.
00725 */
00726 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
00727 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first (void)
00728 {
00729   ACE_TRACE ("ACE_Timer_Wheel_T::remove_first");
00730   return remove_first_expired (ACE_Time_Value::max_time);
00731 }
00732 
00733 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00734 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::unlink (ACE_Timer_Node_T<TYPE>* n)
00735 {
00736   ACE_TRACE ("ACE_Timer_Wheel_T::unlink");
00737   --timer_count_;
00738   n->get_prev ()->set_next (n->get_next ());
00739   n->get_next ()->set_prev (n->get_prev ());
00740   n->set_prev (0);
00741   n->set_next (0);
00742 }
00743 
00744 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
00745 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first_expired (const ACE_Time_Value& now)
00746 {
00747   ACE_Timer_Node_T<TYPE>* n = this->get_first ();
00748   if (n != 0 && n->get_timer_value() <= now)
00749     {
00750       this->unlink (n);
00751       this->recalc_earliest (n->get_timer_value ());
00752       return n;
00753     }
00754   return 0;
00755 }
00756 
00757 /**
00758 * Returns the earliest node without removing it
00759 *
00760 * @return The earliest timer node.
00761 */
00762 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00763 ACE_Timer_Node_T<TYPE>*
00764 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first (void)
00765 {
00766   ACE_TRACE ("ACE_Timer_Wheel_T::get_first");
00767   return this->get_first_i ();
00768 }
00769 
00770 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00771 ACE_Timer_Node_T<TYPE>*
00772 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first_i (void) const
00773 {
00774   ACE_Timer_Node_T<TYPE>* root = this->spokes_[this->earliest_spoke_];
00775   ACE_Timer_Node_T<TYPE>* first = root->get_next ();
00776   if (first != root)
00777     return first;
00778   return 0;
00779 }
00780 
00781 
00782 /**
00783 * @return The iterator
00784 */
00785 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00786 ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>&
00787 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::iter (void)
00788 {
00789   this->iterator_->first ();
00790   return *this->iterator_;
00791 }
00792 
00793 /**
00794 * Dummy version of expire to get rid of warnings in Sun CC 4.2
00795 * Just call the expire of the base class.
00796 */
00797 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00798 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::expire ()
00799 {
00800   return ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::expire ();
00801 }
00802 
00803 /**
00804 * This is a specialized version of expire that is more suited for the
00805 * internal data representation.
00806 *
00807 * @param cur_time The time to expire timers up to.
00808 *
00809 * @return Number of timers expired
00810 */
00811 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00812 ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value& cur_time)
00813 {
00814   ACE_TRACE ("ACE_Timer_Wheel_T::expire");
00815 
00816   int expcount = 0;
00817 
00818   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00819 
00820   ACE_Timer_Node_T<TYPE>* n = this->remove_first_expired (cur_time);
00821 
00822   while (n != 0)
00823     {
00824       ++expcount;
00825 
00826       //ACE_ERROR((LM_ERROR, "Expiring %x\n", (long) n));
00827 
00828       ACE_Timer_Node_Dispatch_Info_T<TYPE> info;
00829 
00830       // Get the dispatch info
00831       n->get_dispatch_info (info);
00832 
00833       if (n->get_interval () > ACE_Time_Value::zero)
00834         {
00835           // Make sure that we skip past values that have already
00836           // "expired".
00837           do
00838             n->set_timer_value (n->get_timer_value () +
00839                                 n->get_interval ());
00840           while (n->get_timer_value () <= cur_time);
00841 
00842           this->reschedule (n);
00843         }
00844       else
00845         {
00846           this->free_node (n);
00847         }
00848 
00849       const void *upcall_act = 0;
00850 
00851       this->preinvoke (info, cur_time, upcall_act);
00852 
00853       this->upcall (info, cur_time);
00854 
00855       this->postinvoke (info, cur_time, upcall_act);
00856 
00857       n = this->remove_first_expired (cur_time);
00858     }
00859 
00860   return expcount;
00861 }
00862 
00863 ///////////////////////////////////////////////////////////////////////////
00864 // ACE_Timer_Wheel_Iterator_T
00865 
00866 /**
00867 * Just initializes the iterator with a ACE_Timer_Wheel_T and then calls
00868 * first() to initialize the rest of itself.
00869 *
00870 * @param wheel A reference for a timer queue to iterate over
00871 */
00872 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00873 ACE_Timer_Wheel_Iterator_T<TYPE,FUNCTOR,ACE_LOCK>::ACE_Timer_Wheel_Iterator_T
00874 (Wheel& wheel)
00875 : timer_wheel_ (wheel)
00876 {
00877   this->first();
00878 }
00879 
00880 
00881 /**
00882 * Destructor, at this level does nothing.
00883 */
00884 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00885 ACE_Timer_Wheel_Iterator_T<TYPE,
00886 FUNCTOR,
00887 ACE_LOCK>::~ACE_Timer_Wheel_Iterator_T (void)
00888 {
00889 }
00890 
00891 
00892 /**
00893 * Positions the iterator at the first position in the timing wheel
00894 * that contains something. spoke_ will be set to the spoke position of
00895 * this entry and current_node_ will point to the first entry in that spoke.
00896 *
00897 * If the wheel is empty, spoke_ will be equal timer_wheel_.spoke_count_ and
00898 * current_node_ would be 0.
00899 */
00900 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00901 ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::first (void)
00902 {
00903   this->goto_next(0);
00904 }
00905 
00906 
00907 /**
00908 * Positions the iterator at the next node.
00909 */
00910 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00911 ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::next (void)
00912 {
00913   if (this->isdone())
00914     return;
00915 
00916   ACE_Timer_Node_T<TYPE>* n = this->current_node_->get_next ();
00917   ACE_Timer_Node_T<TYPE>* root = this->timer_wheel_.spokes_[this->spoke_];
00918   if (n == root)
00919     this->goto_next (this->spoke_ + 1);
00920   else
00921     this->current_node_ = n;
00922 }
00923 
00924 /// Helper class for common functionality of next() and first()
00925 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00926 ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::goto_next (u_int start_spoke)
00927 {
00928   // Find the first non-empty entry.
00929   u_int sc = this->timer_wheel_.spoke_count_;
00930   for (u_int i = start_spoke; i < sc; ++i)
00931   {
00932     ACE_Timer_Node_T<TYPE>* root = this->timer_wheel_.spokes_[i];
00933     ACE_Timer_Node_T<TYPE>* n = root->get_next ();
00934     if (n != root)
00935       {
00936         this->spoke_ = i;
00937         this->current_node_ = n;
00938         return;
00939       }
00940   }
00941   // empty
00942   this->spoke_ = sc;
00943   this->current_node_ = 0;
00944 }
00945 
00946 /**
00947 * @return True when we there aren't any more items (when current_node_ == 0)
00948 */
00949 template <class TYPE, class FUNCTOR, class ACE_LOCK> bool
00950 ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::isdone (void) const
00951 {
00952   return this->current_node_ == 0;
00953 }
00954 
00955 /**
00956 * @return The node at the current spokeition in the sequence or 0 if the wheel
00957 *         is empty
00958 */
00959 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
00960 ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::item (void)
00961 {
00962   return this->current_node_;
00963 }
00964 
00965 ACE_END_VERSIONED_NAMESPACE_DECL
00966 
00967 #endif /* ACE_TIMER_WHEEL_T_CPP */

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