Timer_Queue_T.cpp

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

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