Timer_Queue_T.cpp

Go to the documentation of this file.
00001 // Timer_Queue_T.cpp,v 4.68 2006/04/19 11:54:16 jwillemsen Exp
00002 
00003 #ifndef ACE_TIMER_QUEUE_T_CPP
00004 #define ACE_TIMER_QUEUE_T_CPP
00005 
00006 #include "ace/config-all.h"
00007 
00008 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00009 # pragma once
00010 #endif /* ACE_LACKS_PRAGMA_ONCE */
00011 
00012 #include "ace/Timer_Queue_T.h"
00013 #include "ace/Guard_T.h"
00014 #include "ace/Log_Msg.h"
00015 #include "ace/Reactor_Timer_Interface.h"
00016 #include "ace/Null_Mutex.h"
00017 #include "ace/OS_NS_sys_time.h"
00018 
00019 #if !defined (__ACE_INLINE__)
00020 #include "ace/Timer_Queue_T.inl"
00021 #endif /* __ACE_INLINE__ */
00022 
00023 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00024 
00025 // This fudge factor can be overriden for timers that need it, such as on
00026 // Solaris, by defining the ACE_TIMER_SKEW symbol in the appropriate config
00027 // header.
00028 #if !defined (ACE_TIMER_SKEW)
00029 #  define ACE_TIMER_SKEW 0
00030 #endif /* ACE_TIMER_SKEW */
00031 
00032 template <class TYPE> void
00033 ACE_Timer_Node_T<TYPE>::dump (void) const
00034 {
00035 #if defined (ACE_HAS_DUMP)
00036   ACE_TRACE ("ACE_Timer_Node_T::dump");
00037   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00038   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nact_ = %x"), this->act_));
00039   this->timer_value_.dump ();
00040   this->interval_.dump ();
00041   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nprev_ = %x"), this->prev_));
00042   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nnext_ = %x"), this->next_));
00043   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntimer_id_ = %d\n"), this->timer_id_));
00044   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00045 #endif /* ACE_HAS_DUMP */
00046 }
00047 
00048 template <class TYPE>
00049 ACE_Timer_Node_T<TYPE>::ACE_Timer_Node_T (void)
00050 {
00051   ACE_TRACE ("ACE_Timer_Node_T::ACE_Timer_Node_T");
00052 }
00053 
00054 template <class TYPE>
00055 ACE_Timer_Node_T<TYPE>::~ACE_Timer_Node_T (void)
00056 {
00057   ACE_TRACE ("ACE_Timer_Node_T::~ACE_Timer_Node_T");
00058 }
00059 
00060 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00061 ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Queue_Iterator_T (void)
00062 {
00063 }
00064 
00065 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00066 ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Queue_Iterator_T (void)
00067 {
00068 }
00069 
00070 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Time_Value *
00071 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::calculate_timeout (ACE_Time_Value *max_wait_time)
00072 {
00073   ACE_TRACE ("ACE_Timer_Queue_T::calculate_timeout");
00074   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, max_wait_time));
00075 
00076   if (this->is_empty ())
00077     // Nothing on the Timer_Queue, so use whatever the caller gave us.
00078     return max_wait_time;
00079   else
00080     {
00081       ACE_Time_Value cur_time = this->gettimeofday ();
00082 
00083       if (this->earliest_time () > cur_time)
00084         {
00085           // The earliest item on the Timer_Queue is still in the
00086           // future.  Therefore, use the smaller of (1) caller's wait
00087           // time or (2) the delta time between now and the earliest
00088           // time on the Timer_Queue.
00089 
00090           this->timeout_ = this->earliest_time () - cur_time;
00091           if (max_wait_time == 0 || *max_wait_time > timeout_)
00092             return &this->timeout_;
00093           else
00094             return max_wait_time;
00095         }
00096       else
00097         {
00098           // The earliest item on the Timer_Queue is now in the past.
00099           // Therefore, we've got to "poll" the Reactor, i.e., it must
00100           // just check the descriptors and then dispatch timers, etc.
00101           this->timeout_ = ACE_Time_Value::zero;
00102           return &this->timeout_;
00103         }
00104     }
00105 }
00106 
00107 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Time_Value *
00108 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::calculate_timeout (ACE_Time_Value *max_wait_time,
00109                                                                ACE_Time_Value *the_timeout)
00110 {
00111   ACE_TRACE ("ACE_Timer_Queue_T::calculate_timeout");
00112 
00113   if (the_timeout == 0)
00114     return 0;
00115 
00116   if (this->is_empty ())
00117     {
00118       // Nothing on the Timer_Queue, so use whatever the caller gave us.
00119       if (max_wait_time)
00120         *the_timeout = *max_wait_time;
00121       else
00122         return 0;
00123     }
00124   else
00125     {
00126       ACE_Time_Value cur_time = this->gettimeofday ();
00127 
00128       if (this->earliest_time () > cur_time)
00129         {
00130           // The earliest item on the Timer_Queue is still in the
00131           // future.  Therefore, use the smaller of (1) caller's wait
00132           // time or (2) the delta time between now and the earliest
00133           // time on the Timer_Queue.
00134 
00135           *the_timeout = this->earliest_time () - cur_time;
00136           if (!(max_wait_time == 0 || *max_wait_time > *the_timeout))
00137             *the_timeout = *max_wait_time;
00138         }
00139       else
00140         {
00141           // The earliest item on the Timer_Queue is now in the past.
00142           // Therefore, we've got to "poll" the Reactor, i.e., it must
00143           // just check the descriptors and then dispatch timers, etc.
00144           *the_timeout = ACE_Time_Value::zero;
00145         }
00146     }
00147   return the_timeout;
00148 }
00149 
00150 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00151 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const
00152 {
00153 #if defined (ACE_HAS_DUMP)
00154   ACE_TRACE ("ACE_Timer_Queue_T::dump");
00155   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00156   this->timeout_.dump ();
00157   this->timer_skew_.dump ();
00158   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00159 #endif /* ACE_HAS_DUMP */
00160 }
00161 
00162 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00163 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Queue_T (FUNCTOR *upcall_functor,
00164                                                            ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
00165   : gettimeofday_ (ACE_OS::gettimeofday),
00166     delete_upcall_functor_ (upcall_functor == 0),
00167     delete_free_list_ (freelist == 0),
00168     timer_skew_ (0, ACE_TIMER_SKEW)
00169 {
00170   ACE_TRACE ("ACE_Timer_Queue_T::ACE_Timer_Queue_T");
00171 
00172   if (!freelist)
00173     ACE_NEW (free_list_,
00174              (ACE_Locked_Free_List<ACE_Timer_Node_T<TYPE>,ACE_Null_Mutex>));
00175   else
00176     free_list_ = freelist;
00177 
00178   if (!upcall_functor)
00179     ACE_NEW (upcall_functor_,
00180              FUNCTOR);
00181   else
00182     upcall_functor_ = upcall_functor;
00183 }
00184 
00185 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00186 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Queue_T (void)
00187 {
00188   ACE_TRACE ("ACE_Timer_Queue_T::~ACE_Timer_Queue_T");
00189 
00190   // Cleanup the functor and free_list on the way out
00191   if (this->delete_upcall_functor_)
00192     delete this->upcall_functor_;
00193 
00194   if (this->delete_free_list_)
00195     delete this->free_list_;
00196 }
00197 
00198 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
00199 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::alloc_node (void)
00200 {
00201   return this->free_list_->remove ();
00202 }
00203 
00204 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00205 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::free_node (ACE_Timer_Node_T<TYPE> *node)
00206 {
00207   this->free_list_->add (node);
00208 }
00209 
00210 template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_LOCK &
00211 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::mutex (void)
00212 {
00213   return this->mutex_;
00214 }
00215 
00216 template <class TYPE, class FUNCTOR, class ACE_LOCK> long
00217 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::schedule (const TYPE &type,
00218                                                       const void *act,
00219                                                       const ACE_Time_Value &future_time,
00220                                                       const ACE_Time_Value &interval)
00221 {
00222   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00223 
00224   // Schedule the timer.
00225   long const result =
00226     this->schedule_i (type,
00227                       act,
00228                       future_time,
00229                       interval);
00230 
00231   // Return on failure.
00232   if (result == -1)
00233     return result;
00234 
00235   // Inform upcall functor of successful registration.
00236   this->upcall_functor ().registration (*this,
00237                                         type,
00238                                         act);
00239 
00240   // Return result;
00241   return result;
00242 }
00243 
00244 // Run the <handle_timeout> method for all Timers whose values are <=
00245 // <cur_time>.
00246 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00247 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value &cur_time)
00248 {
00249   ACE_TRACE ("ACE_Timer_Queue_T::expire");
00250   ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00251 
00252   // Keep looping while there are timers remaining and the earliest
00253   // timer is <= the <cur_time> passed in to the method.
00254 
00255   if (this->is_empty ())
00256     return 0;
00257 
00258   int number_of_timers_expired = 0;
00259   int result = 0;
00260 
00261   ACE_Timer_Node_Dispatch_Info_T<TYPE> info;
00262 
00263   while ((result = this->dispatch_info_i (cur_time,
00264                                           info)) != 0)
00265     {
00266       const void *upcall_act = 0;
00267 
00268       this->preinvoke (info, cur_time, upcall_act);
00269 
00270       this->upcall (info, cur_time);
00271 
00272       this->postinvoke (info, cur_time, upcall_act);
00273 
00274       ++number_of_timers_expired;
00275 
00276     }
00277 
00278   ACE_UNUSED_ARG (result);
00279   return number_of_timers_expired;
00280 }
00281 
00282 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00283 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dispatch_info_i (const ACE_Time_Value &cur_time,
00284                                                              ACE_Timer_Node_Dispatch_Info_T<TYPE> &info)
00285 {
00286   ACE_TRACE ("ACE_Timer_Queue_T::dispatch_info_i");
00287 
00288   if (this->is_empty ())
00289     return 0;
00290 
00291   ACE_Timer_Node_T<TYPE> *expired = 0;
00292 
00293   if (this->earliest_time () <= cur_time)
00294     {
00295       expired = this->remove_first ();
00296 
00297       // Get the dispatch info
00298       expired->get_dispatch_info (info);
00299 
00300       // Check if this is an interval timer.
00301       if (expired->get_interval () > ACE_Time_Value::zero)
00302         {
00303           // Make sure that we skip past values that have already
00304           // "expired".
00305           do
00306             expired->set_timer_value (expired->get_timer_value () +
00307                                       expired->get_interval ());
00308           while (expired->get_timer_value () <= cur_time);
00309 
00310           // Since this is an interval timer, we need to reschedule
00311           // it.
00312           this->reschedule (expired);
00313         }
00314       else
00315         {
00316           // Call the factory method to free up the node.
00317           this->free_node (expired);
00318         }
00319 
00320       return 1;
00321     }
00322 
00323   return 0;
00324 }
00325 
00326 template <class TYPE, class FUNCTOR, class ACE_LOCK> void
00327 ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::return_node (ACE_Timer_Node_T<TYPE> *node)
00328 {
00329   ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_));
00330   this->free_node (node);
00331 }
00332 
00333 
00334 template <class ACE_LOCK>
00335 ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::ACE_Event_Handler_Handle_Timeout_Upcall (void)
00336 {
00337 }
00338 
00339 template <class ACE_LOCK>
00340 ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::~ACE_Event_Handler_Handle_Timeout_Upcall (void)
00341 {
00342 }
00343 
00344 template <class ACE_LOCK> int
00345 ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::registration (TIMER_QUEUE &,
00346                                                                  ACE_Event_Handler *event_handler,
00347                                                                  const void *)
00348 {
00349   event_handler->add_reference ();
00350   return 0;
00351 }
00352 
00353 template <class ACE_LOCK> int
00354 ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::preinvoke (TIMER_QUEUE & /* timer_queue */,
00355                                                               ACE_Event_Handler *event_handler,
00356                                                               const void * /* timer_act */,
00357                                                               int /* recurring_timer */,
00358                                                               const ACE_Time_Value & /* cur_time */,
00359                                                               const void *&upcall_act)
00360 {
00361   int requires_reference_counting =
00362     event_handler->reference_counting_policy ().value () ==
00363     ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
00364 
00365   if (requires_reference_counting)
00366     {
00367       event_handler->add_reference ();
00368 
00369       upcall_act = &this->requires_reference_counting_;
00370     }
00371 
00372   return 0;
00373 }
00374 
00375 template <class ACE_LOCK> int
00376 ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::postinvoke (TIMER_QUEUE & /* timer_queue */,
00377                                                                ACE_Event_Handler *event_handler,
00378                                                                const void * /* timer_act */,
00379                                                                int /* recurring_timer */,
00380                                                                const ACE_Time_Value & /* cur_time */,
00381                                                                const void *upcall_act)
00382 {
00383   if (upcall_act == &this->requires_reference_counting_)
00384     {
00385       event_handler->remove_reference ();
00386     }
00387 
00388   return 0;
00389 }
00390 
00391 template <class ACE_LOCK> int
00392 ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::timeout (TIMER_QUEUE &timer_queue,
00393                                                             ACE_Event_Handler *event_handler,
00394                                                             const void *act,
00395                                                             int recurring_timer,
00396                                                             const ACE_Time_Value &cur_time)
00397 {
00398   int requires_reference_counting = 0;
00399 
00400   if (!recurring_timer)
00401     {
00402       requires_reference_counting =
00403         event_handler->reference_counting_policy ().value () ==
00404         ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
00405     }
00406 
00407   // Upcall to the <handler>s handle_timeout method.
00408   if (event_handler->handle_timeout (cur_time, act) == -1)
00409     {
00410       if (event_handler->reactor ())
00411         event_handler->reactor_timer_interface ()->cancel_timer (event_handler, 0);
00412       else
00413         timer_queue.cancel (event_handler, 0); // 0 means "call handle_close()".
00414     }
00415 
00416   if (!recurring_timer &&
00417       requires_reference_counting)
00418     {
00419       event_handler->remove_reference ();
00420     }
00421 
00422   return 0;
00423 }
00424 
00425 template <class ACE_LOCK> int
00426 ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::cancel_type (TIMER_QUEUE &,
00427                                                                 ACE_Event_Handler *event_handler,
00428                                                                 int dont_call,
00429                                                                 int &requires_reference_counting)
00430 {
00431   requires_reference_counting =
00432     event_handler->reference_counting_policy ().value () ==
00433     ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
00434 
00435   // Upcall to the <handler>s handle_close method
00436   if (dont_call == 0)
00437     event_handler->handle_close (ACE_INVALID_HANDLE,
00438                                  ACE_Event_Handler::TIMER_MASK);
00439 
00440   return 0;
00441 }
00442 
00443 template <class ACE_LOCK> int
00444 ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::cancel_timer (TIMER_QUEUE &,
00445                                                                  ACE_Event_Handler *event_handler,
00446                                                                  int,
00447                                                                  int requires_reference_counting)
00448 {
00449   if (requires_reference_counting)
00450     event_handler->remove_reference ();
00451 
00452   return 0;
00453 }
00454 
00455 template <class ACE_LOCK> int
00456 ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::deletion (TIMER_QUEUE &timer_queue,
00457                                                              ACE_Event_Handler *event_handler,
00458                                                              const void *)
00459 {
00460   int requires_reference_counting = 0;
00461 
00462   this->cancel_type (timer_queue,
00463                      event_handler,
00464                      0,
00465                      requires_reference_counting);
00466 
00467   this->cancel_timer (timer_queue,
00468                       event_handler,
00469                       0,
00470                       requires_reference_counting);
00471 
00472   return 0;
00473 }
00474 
00475 ACE_END_VERSIONED_NAMESPACE_DECL
00476 
00477 #endif /* ACE_TIMER_QUEUE_T_CPP */

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