diff options
Diffstat (limited to 'ace/Timer/Timer_Queue_T.cpp')
-rw-r--r-- | ace/Timer/Timer_Queue_T.cpp | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/ace/Timer/Timer_Queue_T.cpp b/ace/Timer/Timer_Queue_T.cpp new file mode 100644 index 00000000000..166e35c60e6 --- /dev/null +++ b/ace/Timer/Timer_Queue_T.cpp @@ -0,0 +1,354 @@ +// $Id$ + +#ifndef ACE_TIMER_QUEUE_T_C +#define ACE_TIMER_QUEUE_T_C + +#include "ace/Synch.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Signal.h" +#include "ace/Timer_Queue_T.h" +#include "ace/Log_Msg.h" + +#if !defined (__ACE_INLINE__) +#include "ace/Timer_Queue_T.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(ace, Timer_Queue_T, "$Id$") + +template <class TYPE> void +ACE_Timer_Node_T<TYPE>::dump (void) const +{ + ACE_TRACE ("ACE_Timer_Node_T::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nact_ = %x"), this->act_)); + this->timer_value_.dump (); + this->interval_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nprev_ = %x"), this->prev_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nnext_ = %x"), this->next_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntimer_id_ = %d\n"), this->timer_id_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class TYPE> +ACE_Timer_Node_T<TYPE>::ACE_Timer_Node_T (void) +{ + ACE_TRACE ("ACE_Timer_Node_T::ACE_Timer_Node_T"); +} + +template <class TYPE> +ACE_Timer_Node_T<TYPE>::~ACE_Timer_Node_T (void) +{ + ACE_TRACE ("ACE_Timer_Node_T::~ACE_Timer_Node_T"); +} + + + +template <class TYPE, class FUNCTOR, class ACE_LOCK> +ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Queue_Iterator_T (void) +{ +} + +template <class TYPE, class FUNCTOR, class ACE_LOCK> +ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Queue_Iterator_T (void) +{ +} + +// Determines the minimum amount of time that the Reactor must wait +// before timing out. This is computed as the smaller of (1) the +// amount the caller requested when calling handle_events() and (2) +// the earliest time registered in the Timer Queue (if any). Must be +// called with an external lock held since it returns a pointer to a +// Time_Value type stored in the Timer_Queue type itself. If some +// external lock isn't held we'll have reentrancy problems! + +template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Time_Value * +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::calculate_timeout (ACE_Time_Value *max_wait_time) +{ + ACE_TRACE ("ACE_Timer_Queue_T::calculate_timeout"); + ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, max_wait_time)); + + if (this->is_empty ()) + // Nothing on the Timer_Queue, so use whatever the caller gave us. + return max_wait_time; + else + { + ACE_Time_Value cur_time = this->gettimeofday (); + + if (this->earliest_time () > cur_time) + { + // The earliest item on the Timer_Queue is still in the + // future. Therefore, use the smaller of (1) caller's wait + // time or (2) the delta time between now and the earliest + // time on the Timer_Queue. + + this->timeout_ = this->earliest_time () - cur_time; + if (max_wait_time == 0 || *max_wait_time > timeout_) + return &this->timeout_; + else + return max_wait_time; + } + else + { + // The earliest item on the Timer_Queue is now in the past. + // Therefore, we've got to "poll" the Reactor, i.e., it must + // just check the descriptors and then dispatch timers, etc. + this->timeout_ = ACE_Time_Value::zero; + return &this->timeout_; + } + } +} + +template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Time_Value * +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::calculate_timeout (ACE_Time_Value *max_wait_time, + ACE_Time_Value *the_timeout) +{ + ACE_TRACE ("ACE_Timer_Queue_T::calculate_timeout"); + + if (the_timeout == 0) + return 0; + + if (this->is_empty ()) + { + // Nothing on the Timer_Queue, so use whatever the caller gave us. + if (max_wait_time) + *the_timeout = *max_wait_time; + else + return 0; + } + else + { + ACE_Time_Value cur_time = this->gettimeofday (); + + if (this->earliest_time () > cur_time) + { + // The earliest item on the Timer_Queue is still in the + // future. Therefore, use the smaller of (1) caller's wait + // time or (2) the delta time between now and the earliest + // time on the Timer_Queue. + + *the_timeout = this->earliest_time () - cur_time; + if (!(max_wait_time == 0 || *max_wait_time > *the_timeout)) + *the_timeout = *max_wait_time; + } + else + { + // The earliest item on the Timer_Queue is now in the past. + // Therefore, we've got to "poll" the Reactor, i.e., it must + // just check the descriptors and then dispatch timers, etc. + *the_timeout = ACE_Time_Value::zero; + } + } + return the_timeout; +} + +template <class TYPE, class FUNCTOR, class ACE_LOCK> void +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const +{ + ACE_TRACE ("ACE_Timer_Queue_T::dump"); + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + this->timeout_.dump (); + this->timer_skew_.dump (); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} + +template <class TYPE, class FUNCTOR, class ACE_LOCK> +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Queue_T (FUNCTOR *upcall_functor, + ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist) + : gettimeofday_ (ACE_OS::gettimeofday), + delete_upcall_functor_ (upcall_functor == 0), + delete_free_list_ (freelist == 0), + timer_skew_ (0, ACE_TIMER_SKEW) +{ + ACE_TRACE ("ACE_Timer_Queue_T::ACE_Timer_Queue_T"); + + if (!freelist) + ACE_NEW (free_list_, + (ACE_Locked_Free_List<ACE_Timer_Node_T<TYPE>,ACE_Null_Mutex>)); + else + free_list_ = freelist; + + if (!upcall_functor) + ACE_NEW (upcall_functor_, + FUNCTOR); + else + upcall_functor_ = upcall_functor; +} + +template <class TYPE, class FUNCTOR, class ACE_LOCK> +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Queue_T (void) +{ + ACE_TRACE ("ACE_Timer_Queue_T::~ACE_Timer_Queue_T"); + + // Cleanup the functor and free_list on the way out + if (this->delete_upcall_functor_) + delete this->upcall_functor_; + + if (this->delete_free_list_) + delete this->free_list_; +} + +template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> * +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::alloc_node (void) +{ + return this->free_list_->remove (); +} + +template <class TYPE, class FUNCTOR, class ACE_LOCK> void +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::free_node (ACE_Timer_Node_T<TYPE> *node) +{ + this->free_list_->add (node); +} + +template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_LOCK & +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::mutex (void) +{ + return this->mutex_; +} + + +// Run the <handle_timeout> method for all Timers whose values are <= +// <cur_time>. +template <class TYPE, class FUNCTOR, class ACE_LOCK> int +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value &cur_time) +{ + ACE_TRACE ("ACE_Timer_Queue_T::expire"); + ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1)); + + // Keep looping while there are timers remaining and the earliest + // timer is <= the <cur_time> passed in to the method. + + if (this->is_empty ()) + return 0; + + int number_of_timers_expired = 0; + int result = 0; + + ACE_Timer_Node_Dispatch_Info_T<TYPE> info; + + while ((result = this->dispatch_info_i (cur_time, + info)) != 0) + { + // call the functor + this->upcall (info.type_, info.act_, cur_time); + + number_of_timers_expired++; + + } + + ACE_UNUSED_ARG (result); + return number_of_timers_expired; +} + + +template <class TYPE, class FUNCTOR, class ACE_LOCK> int +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::dispatch_info_i (const ACE_Time_Value &cur_time, + ACE_Timer_Node_Dispatch_Info_T<TYPE> &info) +{ + ACE_TRACE ("ACE_Timer_Queue_T::dispatch_info_i"); + + if (this->is_empty ()) + return 0; + + ACE_Timer_Node_T<TYPE> *expired = 0; + + if (this->earliest_time () <= cur_time) + { + expired = this->remove_first (); + + // Get the dispatch info + expired->get_dispatch_info (info); + + // Check if this is an interval timer. + if (expired->get_interval () > ACE_Time_Value::zero) + { + // Make sure that we skip past values that have already + // "expired". + do + expired->set_timer_value (expired->get_timer_value () + expired->get_interval ()); + while (expired->get_timer_value () <= cur_time); + + // Since this is an interval timer, we need to reschedule + // it. + this->reschedule (expired); + } + else + { + // Call the factory method to free up the node. + this->free_node (expired); + } + + return 1; + } + + return 0; +} + + +template <class TYPE, class FUNCTOR, class ACE_LOCK> void +ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>::return_node (ACE_Timer_Node_T<TYPE> *node) +{ + ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_)); + this->free_node (node); +} + + +template <class ACE_LOCK> +ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::ACE_Event_Handler_Handle_Timeout_Upcall (void) +{ +} + +template <class ACE_LOCK> +ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::~ACE_Event_Handler_Handle_Timeout_Upcall (void) +{ +} + +template <class ACE_LOCK> int +ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::timeout (ACE_Timer_Queue_T<ACE_Event_Handler *, + ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>, + ACE_LOCK> &timer_queue, + ACE_Event_Handler *handler, + const void *act, + const ACE_Time_Value &cur_time) +{ + // Upcall to the <handler>s handle_timeout method. + if (handler->handle_timeout (cur_time, act) == -1) + timer_queue.cancel (handler, 0); // 0 means "call handle_close()". + + return 0; +} + +template <class ACE_LOCK> int +ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::cancellation (ACE_Timer_Queue_T<ACE_Event_Handler *, + ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>, + ACE_LOCK> &timer_queue, + ACE_Event_Handler *handler) +{ + ACE_UNUSED_ARG (timer_queue); + + // Upcall to the <handler>s handle_close method + handler->handle_close (ACE_INVALID_HANDLE, + ACE_Event_Handler::TIMER_MASK); + return 0; +} + +template <class ACE_LOCK> int +ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>::deletion (ACE_Timer_Queue_T<ACE_Event_Handler *, + ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>, + ACE_LOCK> &timer_queue, + ACE_Event_Handler *handler, + const void *arg) +{ + ACE_UNUSED_ARG (timer_queue); + ACE_UNUSED_ARG (handler); + ACE_UNUSED_ARG (arg); + + // Does nothing + + return 0; +} + +#endif /* ACE_TIMER_QUEUE_T_C*/ |