Timer_Hash_T.cpp

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

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