Timer_Hash_T.cpp

Go to the documentation of this file.
00001 // $Id: Timer_Hash_T.cpp 79134 2007-07-31 18:23:50Z johnnyw $
00002 
00003 #ifndef ACE_TIMER_HASH_T_C
00004 #define ACE_TIMER_HASH_T_C
00005 
00006 #include "ace/Timer_Hash_T.h"
00007 
00008 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00009 # pragma once
00010 #endif /* ACE_LACKS_PRAGMA_ONCE */
00011 
00012 #include "ace/OS_NS_sys_time.h"
00013 #include "ace/Guard_T.h"
00014 #include "ace/Log_Msg.h"
00015 #include "ace/Truncate.h"
00016 
00017 ACE_RCSID(ace,
00018           Timer_Hash_T,
00019           "$Id: Timer_Hash_T.cpp 79134 2007-07-31 18:23:50Z johnnyw $")
00020 
00021 template <class TYPE>
00022 struct Hash_Token
00023 {
00024   Hash_Token (const void *act,
00025               size_t pos,
00026               long orig_id,
00027               const TYPE &type)
00028     : act_ (act),
00029       pos_ (pos),
00030       orig_id_ (orig_id),
00031       type_ (type)
00032   {}
00033 
00034   const void *act_;
00035   size_t pos_;
00036   long orig_id_;
00037   TYPE type_;
00038 };
00039 
00040 // Default constructor
00041 
00042 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00043 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Hash_Upcall (void)
00044   : timer_hash_ (0)
00045 {
00046   // Nothing
00047 }
00048 
00049 // Constructor that specifies a Timer_Hash to call up to
00050 
00051 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00052 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Hash_Upcall (ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> *timer_hash)
00053   : timer_hash_ (timer_hash)
00054 {
00055   // Nothing
00056 }
00057 
00058 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00059 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::registration (TIMER_QUEUE &,
00060                                                               ACE_Event_Handler *,
00061                                                               const void *)
00062 {
00063   // Registration will be handled by the upcall functor of the timer
00064   // hash.
00065   return 0;
00066 }
00067 
00068 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00069 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::preinvoke (TIMER_QUEUE &,
00070                                                            ACE_Event_Handler *,
00071                                                            const void *,
00072                                                            int,
00073                                                            const ACE_Time_Value &,
00074                                                            const void *&)
00075 {
00076   // This method should never be invoked since we don't invoke
00077   // expire() on the buckets.
00078   ACE_ASSERT (0);
00079   return 0;
00080 }
00081 
00082 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00083 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::postinvoke (TIMER_QUEUE &,
00084                                                             ACE_Event_Handler *,
00085                                                             const void *,
00086                                                             int,
00087                                                             const ACE_Time_Value &,
00088                                                             const void *)
00089 {
00090   // This method should never be invoked since we don't invoke
00091   // expire() on the buckets.
00092   ACE_ASSERT (0);
00093   return 0;
00094 }
00095 
00096 // Calls up to timer_hash's upcall functor
00097 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00098 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::timeout (TIMER_QUEUE &,
00099                                                          ACE_Event_Handler *,
00100                                                          const void *,
00101                                                          int,
00102                                                          const ACE_Time_Value &)
00103 {
00104   // This method should never be invoked since we don't invoke
00105   // expire() on the buckets.
00106   ACE_ASSERT (0);
00107   return 0;
00108 }
00109 
00110 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00111 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::cancel_type (TIMER_QUEUE &,
00112                                                              ACE_Event_Handler *,
00113                                                              int,
00114                                                              int &)
00115 {
00116   // Cancellation will be handled by the upcall functor of the timer
00117   // hash.
00118   return 0;
00119 }
00120 
00121 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00122 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::cancel_timer (TIMER_QUEUE &,
00123                                                               ACE_Event_Handler *,
00124                                                               int,
00125                                                               int)
00126 {
00127   // Cancellation will be handled by the upcall functor of the timer
00128   // hash.
00129   return 0;
00130 }
00131 
00132 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00133 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::deletion (TIMER_QUEUE &,
00134                                                           ACE_Event_Handler *event_handler,
00135                                                           const void *arg)
00136 {
00137   // Call up to the upcall functor of the timer hash since the timer
00138   // hash does not invoke deletion() on its upcall functor directly.
00139   Hash_Token<TYPE> *h =
00140     reinterpret_cast<Hash_Token<TYPE> *> (const_cast<void *> (arg));
00141 
00142   int result =
00143     this->timer_hash_->upcall_functor ().
00144     deletion (*this->timer_hash_,
00145               event_handler,
00146               h->act_);
00147 
00148   delete h;
00149 
00150   return result;
00151 }
00152 
00153 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
00154 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::ACE_Timer_Hash_Iterator_T (ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET> &hash)
00155   : timer_hash_ (hash)
00156 {
00157   this->first ();
00158   // Nothing
00159 }
00160 
00161 // Positions the iterator at the first node in the timing hash table
00162 
00163 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
00164 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::first (void)
00165 {
00166   for (this->position_ = 0;
00167        this->position_ < this->timer_hash_.table_size_;
00168        ++this->position_)
00169     {
00170       // Check for an empty entry
00171       if (!this->timer_hash_.table_[this->position_]->is_empty ())
00172         {
00173           this->iter_ = &this->timer_hash_.table_[this->position_]->iter ();
00174           this->iter_->first ();
00175           return;
00176         }
00177     }
00178 
00179   // Didn't find any
00180   this->iter_ = 0;
00181 }
00182 
00183 // Positions the iterator at the next node in the bucket or goes to the next
00184 // bucket
00185 
00186 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
00187 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::next (void)
00188 {
00189   if (this->isdone ())
00190     return;
00191 
00192   // If there is no more in the current bucket, go to the next
00193   if (this->iter_->isdone ())
00194     {
00195       for (++this->position_;
00196            this->position_ < this->timer_hash_.table_size_;
00197            ++this->position_)
00198         {
00199           // Check for an empty entry
00200           if (!this->timer_hash_.table_[this->position_]->is_empty ())
00201             {
00202               this->iter_ = &this->timer_hash_.table_[this->position_]->iter ();
00203               this->iter_->first ();
00204               return;
00205             }
00206         }
00207 
00208       // Didn't find any.
00209       this->iter_ = 0;
00210     }
00211   else
00212     this->iter_->next ();
00213 }
00214 
00215 // Returns true when we are at the end (when bucket_item_ == 0)
00216 
00217 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00218 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::isdone (void) const
00219 {
00220   return this->iter_ == 0;
00221 }
00222 
00223 // Returns the node at the current position in the sequence
00224 
00225 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> ACE_Timer_Node_T<TYPE> *
00226 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::item (void)
00227 {
00228   if (this->isdone ())
00229     return 0;
00230 
00231   return this->iter_->item ();
00232 }
00233 
00234 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> &
00235 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::iter (void)
00236 {
00237   this->iterator_->first ();
00238   return *this->iterator_;
00239 }
00240 
00241 // Create an empty queue.
00242 
00243 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
00244 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::ACE_Timer_Hash_T (size_t table_size,
00245                                                                      FUNCTOR *upcall_functor,
00246                                                                      ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
00247   : ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> (upcall_functor, freelist),
00248     size_ (0),
00249     table_size_ (table_size),
00250     table_functor_ (this),
00251     earliest_position_ (0)
00252 #if defined (ACE_WIN64)
00253   , pointer_base_ (0)
00254 #endif /* ACE_WIN64 */
00255 {
00256   ACE_TRACE ("ACE_Timer_Hash_T::ACE_Timer_Hash_T");
00257 
00258   ACE_NEW (table_,
00259            BUCKET *[table_size]);
00260 
00261   this->gettimeofday (ACE_OS::gettimeofday);
00262 
00263   for (size_t i = 0;
00264        i < table_size;
00265        ++i)
00266     {
00267       ACE_NEW (this->table_[i],
00268                BUCKET (&this->table_functor_,
00269                        this->free_list_));
00270       this->table_[i]->gettimeofday (ACE_OS::gettimeofday);
00271     }
00272 
00273   ACE_NEW (iterator_,
00274            HASH_ITERATOR (*this));
00275 }
00276 
00277 
00278 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
00279 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::ACE_Timer_Hash_T (FUNCTOR *upcall_functor,
00280                                                                      ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
00281   : ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> (upcall_functor, freelist),
00282     size_ (0),
00283     table_size_ (ACE_DEFAULT_TIMER_HASH_TABLE_SIZE),
00284     table_functor_ (this),
00285     earliest_position_ (0)
00286 #if defined (ACE_WIN64)
00287   , pointer_base_ (0)
00288 #endif /* ACE_WIN64 */
00289 {
00290   ACE_TRACE ("ACE_Timer_Hash_T::ACE_Timer_Hash_T");
00291 
00292   ACE_NEW (table_,
00293            BUCKET *[ACE_DEFAULT_TIMER_HASH_TABLE_SIZE]);
00294 
00295 
00296   this->gettimeofday (ACE_OS::gettimeofday);
00297 
00298   for (size_t i = 0;
00299        i < this->table_size_;
00300        ++i)
00301     {
00302       ACE_NEW (this->table_[i],
00303                BUCKET (&this->table_functor_,
00304                        this->free_list_));
00305       this->table_[i]->gettimeofday (ACE_OS::gettimeofday);
00306     }
00307 
00308   ACE_NEW (iterator_,
00309            HASH_ITERATOR (*this));
00310 }
00311 
00312 // Remove all remaining items in the Queue.
00313 
00314 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
00315 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::~ACE_Timer_Hash_T (void)
00316 {
00317   ACE_TRACE ("ACE_Timer_Hash_T::~ACE_Timer_Hash_T");
00318   ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_));
00319 
00320   delete iterator_;
00321 
00322   for (size_t i = 0;
00323        i < this->table_size_;
00324        ++i)
00325     delete this->table_[i];
00326 
00327   delete [] this->table_;
00328 }
00329 
00330 // Checks if queue is empty.
00331 
00332 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00333 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::is_empty (void) const
00334 {
00335   ACE_TRACE ("ACE_Timer_Hash_T::is_empty");
00336   return this->table_[this->earliest_position_]->is_empty ();
00337 }
00338 
00339 // Returns earliest time in a non-empty bucket
00340 
00341 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> const ACE_Time_Value &
00342 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::earliest_time (void) const
00343 {
00344   ACE_TRACE ("ACE_Timer_Hash_T::earliest_time");
00345   return this->table_[this->earliest_position_]->earliest_time ();
00346 }
00347 
00348 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
00349 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::dump (void) const
00350 {
00351 #if defined (ACE_HAS_DUMP)
00352   ACE_TRACE ("ACE_Timer_Hash_T::dump");
00353   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00354   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntable_size_ = %d"), this->table_size_));
00355   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nearliest_position_ = %d"), this->earliest_position_));
00356 
00357   for (size_t i = 0; i < this->table_size_; ++i)
00358     if (!this->table_[i]->is_empty ())
00359       ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nBucket %d contains nodes"), i));
00360 
00361   ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
00362   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00363 #endif /* ACE_HAS_DUMP */
00364 }
00365 
00366 // Reschedule a periodic timer.  This function must be called with the
00367 // mutex lock held.
00368 
00369 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
00370 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::reschedule (ACE_Timer_Node_T<TYPE> *expired)
00371 {
00372   ACE_TRACE ("ACE_Timer_Hash_T::reschedule");
00373 
00374   Hash_Token<TYPE> *h =
00375     reinterpret_cast<Hash_Token<TYPE> *> (
00376       const_cast<void *> (expired->get_act ()));
00377 
00378   size_t secs_hash_input =
00379     ACE_Utils::truncate_cast<size_t> (expired->get_timer_value ().sec ());
00380   h->pos_ = secs_hash_input % this->table_size_;
00381 
00382   h->orig_id_ =
00383     this->table_[h->pos_]->schedule (expired->get_type (),
00384                                      h,
00385                                      expired->get_timer_value (),
00386                                      expired->get_interval ());
00387   ACE_ASSERT (h->orig_id_ != -1);
00388 
00389 #if 0
00390   ACE_DEBUG ((LM_DEBUG, "Hash::reschedule() resets %d in slot %d where it's id is %d and token is %x\n",
00391               expired->get_timer_value ().msec (),
00392               h->pos_,
00393               h->orig_id_,
00394               h));
00395 #endif
00396 
00397   if (this->table_[this->earliest_position_]->is_empty ()
00398       || this->table_[h->pos_]->earliest_time ()
00399       < this->table_[this->earliest_position_]->earliest_time ())
00400     this->earliest_position_ = h->pos_;
00401 }
00402 
00403 // Insert a new handler that expires at time future_time; if interval
00404 // is > 0, the handler will be reinvoked periodically.
00405 
00406 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> long
00407 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::schedule_i (const TYPE &type,
00408                                                                const void *act,
00409                                                                const ACE_Time_Value &future_time,
00410                                                                const ACE_Time_Value &interval)
00411 {
00412   ACE_TRACE ("ACE_Timer_Hash_T::schedule_i");
00413 
00414   size_t secs_hash_input = ACE_Utils::truncate_cast<size_t> (future_time.sec ());
00415   size_t position = secs_hash_input % this->table_size_;
00416 
00417   Hash_Token<TYPE> *h = 0;
00418 
00419   ACE_NEW_RETURN (h,
00420                   Hash_Token<TYPE> (act,
00421                                     position,
00422                                     0,
00423                                     type),
00424                   -1);
00425 
00426   h->orig_id_ =
00427     this->table_[position]->schedule (type,
00428                                       h,
00429                                       future_time,
00430                                       interval);
00431   ACE_ASSERT (h->orig_id_ != -1);
00432 
00433 #if 0
00434   ACE_DEBUG ((LM_DEBUG, "Hash::schedule() placing %d in slot %d where it's id is %d and token is %x\n",
00435               future_time.msec (),
00436               position,
00437               h->orig_id_,
00438               h));
00439 #endif
00440 
00441   if (this->table_[this->earliest_position_]->is_empty ()
00442       || this->table_[position]->earliest_time ()
00443       < this->table_[this->earliest_position_]->earliest_time ())
00444     this->earliest_position_ = position;
00445 
00446   ++this->size_;
00447 
00448 #if defined (ACE_WIN64)
00449   // This is a Win64 hack, necessary because of the original (bad) decision
00450   // to use a pointer as the timer ID. This class doesn't follow the usual
00451   // timer expiration rules (see comments in header file) and is probably
00452   // not used much. The dynamic allocation of Hash_Tokens without
00453   // recording them anywhere is a large problem for Win64 since the
00454   // size of a pointer is 64 bits, but a long is 32. Since this class
00455   // is not much used, I'm hacking this, at least for now. If it becomes
00456   // an issue, I'll look at it again then.
00457   intptr_t hi = reinterpret_cast<intptr_t> (h);
00458   if (this->pointer_base_ == 0)
00459     this->pointer_base_ = hi & 0xffffffff00000000;
00460   return static_cast<long> (hi & 0xffffffff);
00461 #else
00462   return reinterpret_cast<long> (h);
00463 #endif
00464 }
00465 
00466 // Locate and update the inteval on the timer_id
00467 
00468 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00469 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::reset_interval (long timer_id,
00470                                                                    const ACE_Time_Value &interval)
00471 {
00472   ACE_TRACE ("ACE_Timer_Hash_T::reset_interval");
00473   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00474 
00475   // Make sure we are getting a valid <timer_id>, not an error
00476   // returned by <schedule>.
00477   if (timer_id == -1)
00478     return -1;
00479 
00480 
00481 #if defined (ACE_WIN64)
00482   unsigned long timer_offset = static_cast<unsigned long> (timer_id);
00483   Hash_Token<TYPE> *h =
00484     reinterpret_cast<Hash_Token<TYPE> *> (this->pointer_base_ + timer_offset);
00485 #else
00486   Hash_Token<TYPE> *h =
00487     reinterpret_cast<Hash_Token<TYPE> *> (timer_id);
00488 #endif /* ACE_WIN64 */
00489 
00490   return this->table_[h->pos_]->reset_interval (h->orig_id_,
00491                                                 interval);
00492 }
00493 
00494 // Locate and remove the single <ACE_Event_Handler> with a value of
00495 // <timer_id> from the correct table timer queue.
00496 
00497 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00498 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::cancel (long timer_id,
00499                                                            const void **act,
00500                                                            int dont_call)
00501 {
00502   ACE_TRACE ("ACE_Timer_Hash_T::cancel");
00503   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00504 
00505   // Make sure we are getting a valid <timer_id>, not an error
00506   // returned by <schedule>.
00507   if (timer_id == -1)
00508     return 0;
00509 
00510 #if defined (ACE_WIN64)
00511   unsigned long timer_offset = static_cast<unsigned long> (timer_id);
00512   Hash_Token<TYPE> *h =
00513     reinterpret_cast<Hash_Token<TYPE> *> (this->pointer_base_ + timer_offset);
00514 #else
00515   Hash_Token<TYPE> *h =
00516     reinterpret_cast<Hash_Token<TYPE> *> (timer_id);
00517 #endif /* ACE_WIN64 */
00518 
00519   int const result = this->table_[h->pos_]->cancel (h->orig_id_,
00520                                                     0,
00521                                                     dont_call);
00522 
00523   if (result == 1)
00524     {
00525       // Call the close hooks.
00526       int cookie = 0;
00527 
00528       // cancel_type() called once per <type>.
00529       this->upcall_functor ().cancel_type (*this,
00530                                            h->type_,
00531                                            dont_call,
00532                                            cookie);
00533 
00534       // cancel_timer() called once per <timer>.
00535       this->upcall_functor ().cancel_timer (*this,
00536                                             h->type_,
00537                                             dont_call,
00538                                             cookie);
00539 
00540       if (h->pos_ == this->earliest_position_)
00541         this->find_new_earliest ();
00542 
00543       if (act != 0)
00544         *act = h->act_;
00545 
00546       delete h;
00547 
00548       --this->size_;
00549     }
00550 
00551   return result;
00552 }
00553 
00554 // Locate and remove all values of <type> from the timer queue.
00555 
00556 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00557 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::cancel (const TYPE &type,
00558                                                            int dont_call)
00559 {
00560   ACE_TRACE ("ACE_Timer_Hash_T::cancel");
00561 
00562   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00563 
00564   size_t i; // loop variable.
00565 
00566   Hash_Token<TYPE> **timer_ids = 0;
00567 
00568   ACE_NEW_RETURN (timer_ids,
00569                   Hash_Token<TYPE> *[this->size_],
00570                   -1);
00571   size_t pos = 0;
00572 
00573   for (i = 0;
00574        i < this->table_size_;
00575        ++i)
00576     {
00577       ACE_Timer_Queue_Iterator_T<TYPE,
00578                                  ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>,
00579                                  ACE_Null_Mutex> &iter =
00580         this->table_[i]->iter ();
00581 
00582       for (iter.first ();
00583            !iter.isdone ();
00584            iter.next ())
00585         if (iter.item ()->get_type () == type)
00586           timer_ids[pos++] =
00587             reinterpret_cast<Hash_Token<TYPE> *> (
00588               const_cast<void *> (iter.item ()->get_act ()));
00589     }
00590 
00591   if (pos > this->size_)
00592     return -1;
00593 
00594   for (i = 0; i < pos; ++i)
00595     {
00596       int const result =
00597         this->table_[timer_ids[i]->pos_]->cancel (timer_ids[i]->orig_id_,
00598                                                   0,
00599                                                   dont_call);
00600       ACE_ASSERT (result == 1);
00601       ACE_UNUSED_ARG (result);
00602 
00603       delete timer_ids[i];
00604 
00605       --this->size_;
00606     }
00607 
00608   delete [] timer_ids;
00609 
00610   this->find_new_earliest ();
00611 
00612   // Call the close hooks.
00613   int cookie = 0;
00614 
00615   // cancel_type() called once per <type>.
00616   this->upcall_functor ().cancel_type (*this,
00617                                        type,
00618                                        dont_call,
00619                                        cookie);
00620 
00621   for (i = 0;
00622        i < pos;
00623        ++i)
00624     {
00625       // cancel_timer() called once per <timer>.
00626       this->upcall_functor ().cancel_timer (*this,
00627                                             type,
00628                                             dont_call,
00629                                             cookie);
00630     }
00631 
00632   return static_cast<int> (pos);
00633 }
00634 
00635 // Removes the earliest node and finds the new earliest position
00636 
00637 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> ACE_Timer_Node_T<TYPE> *
00638 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::remove_first (void)
00639 {
00640   if (this->is_empty ())
00641     return 0;
00642 
00643   ACE_Timer_Node_T<TYPE> *temp =
00644     this->table_[this->earliest_position_]->remove_first ();
00645 
00646   this->find_new_earliest ();
00647 
00648   --this->size_;
00649 
00650   return temp;
00651 }
00652 
00653 // Finds a new earliest position
00654 
00655 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
00656 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::find_new_earliest (void)
00657 {
00658   for (size_t i = 0; i < this->table_size_; ++i)
00659     if (!this->table_[i]->is_empty ())
00660       if (this->table_[this->earliest_position_]->is_empty ()
00661           || this->earliest_time () == ACE_Time_Value::zero
00662           || this->table_[i]->earliest_time () <= this->earliest_time ())
00663           this->earliest_position_ = i;
00664 }
00665 
00666 // Returns the earliest node without removing it
00667 
00668 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> ACE_Timer_Node_T<TYPE> *
00669 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::get_first (void)
00670 {
00671   ACE_TRACE ("ACE_Timer_Hash_T::get_first");
00672 
00673   if (this->is_empty ())
00674     return 0;
00675 
00676   return this->table_[this->earliest_position_]->get_first ();
00677 }
00678 
00679 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00680 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::dispatch_info_i (const ACE_Time_Value &cur_time,
00681                                                                     ACE_Timer_Node_Dispatch_Info_T<TYPE> &info)
00682 {
00683   int const result =
00684     ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::dispatch_info_i (cur_time,
00685                                                                info);
00686 
00687   if (result == 1)
00688     {
00689       Hash_Token<TYPE> *h =
00690         reinterpret_cast<Hash_Token<TYPE> *> (const_cast<void *> (info.act_));
00691 
00692       info.act_ = h->act_;
00693     }
00694 
00695   return result;
00696 }
00697 
00698 // Dummy version of expire to get rid of warnings in Sun CC 4.2
00699 
00700 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00701 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::expire ()
00702 {
00703   return ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::expire();
00704 }
00705 
00706 // Specialized expire for Timer Hash
00707 
00708 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00709 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::expire (const ACE_Time_Value &cur_time)
00710 {
00711   ACE_TRACE ("ACE_Timer_Hash_T::expire");
00712   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00713 
00714   int number_of_timers_expired = 0;
00715 
00716   ACE_Timer_Node_T<TYPE> *expired = 0;
00717 
00718   // Go through the table and expire anything that can be expired
00719 
00720   for (size_t i = 0;
00721        i < this->table_size_;
00722        ++i)
00723     {
00724       while (!this->table_[i]->is_empty ()
00725              && this->table_[i]->earliest_time () <= cur_time)
00726         {
00727           expired = this->table_[i]->remove_first ();
00728           const void *act = expired->get_act ();
00729           int reclaim = 1;
00730 
00731           Hash_Token<TYPE> *h =
00732             reinterpret_cast<Hash_Token<TYPE> *> (const_cast<void *> (act));
00733 
00734           ACE_ASSERT (h->pos_ == i);
00735 
00736 #if 0
00737           ACE_DEBUG ((LM_DEBUG, "Hash::expire() expiring %d in slot %d where it's id is %d and token is %x\n",
00738                       expired->get_timer_value ().msec (),
00739                       h->pos_,
00740                       h->orig_id_,
00741                       h));
00742 #endif
00743 
00744           // Check if this is an interval timer.
00745           if (expired->get_interval () > ACE_Time_Value::zero)
00746             {
00747               // Make sure that we skip past values that have already
00748               // "expired".
00749               do
00750                 expired->set_timer_value (expired->get_timer_value ()
00751                                           + expired->get_interval ());
00752               while (expired->get_timer_value () <= cur_time);
00753 
00754               // Since this is an interval timer, we need to
00755               // reschedule it.
00756               this->reschedule (expired);
00757               reclaim = 0;
00758             }
00759 
00760           ACE_Timer_Node_Dispatch_Info_T<TYPE> info;
00761 
00762           // Get the dispatch info
00763           expired->get_dispatch_info (info);
00764 
00765           info.act_ = h->act_;
00766 
00767           const void *upcall_act = 0;
00768 
00769           this->preinvoke (info, cur_time, upcall_act);
00770 
00771           this->upcall (info, cur_time);
00772 
00773           this->postinvoke (info, cur_time, upcall_act);
00774 
00775           if (reclaim)
00776             {
00777               --this->size_;
00778               delete h;
00779             }
00780 
00781           ++number_of_timers_expired;
00782          }
00783     }
00784 
00785   if (number_of_timers_expired > 0)
00786     this->find_new_earliest ();
00787 
00788   return number_of_timers_expired;
00789 }
00790 
00791 #endif /* ACE_TIMER_HASH_T_C */

Generated on Sun Jan 27 12:05:41 2008 for ACE by doxygen 1.3.6