Timer_Queue_T.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 //=============================================================================
00004 /**
00005  *  @file    Timer_Queue_T.h
00006  *
00007  *  Timer_Queue_T.h,v 4.76 2006/04/27 11:17:56 jwillemsen Exp
00008  *
00009  *  @author Doug Schmidt <schmidt@cs.wustl.edu>
00010  *  @author Irfan Pyarali <irfan@cs.wustl.edu> and
00011  *  @author Darrell Brunsch <brunsch@cs.wustl.edu>
00012  */
00013 //=============================================================================
00014 
00015 #ifndef ACE_TIMER_QUEUE_T_H
00016 #define ACE_TIMER_QUEUE_T_H
00017 #include /**/ "ace/pre.h"
00018 
00019 #include "ace/Free_List.h"
00020 
00021 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00022 # pragma once
00023 #endif /* ACE_LACKS_PRAGMA_ONCE */
00024 
00025 #include "ace/Event_Handler.h"
00026 #include "ace/Time_Value.h"
00027 
00028 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00029 
00030 /**
00031  * @class ACE_Timer_Node_Dispatch_Info_T
00032  *
00033  * @brief Maintains generated dispatch information for Timer nodes.
00034  *
00035  */
00036 template <class TYPE>
00037 class ACE_Timer_Node_Dispatch_Info_T
00038 {
00039 public:
00040   /// The type of object held in the queue
00041   TYPE type_;
00042 
00043   /// Asynchronous completion token associated with the timer.
00044   const void *act_;
00045 
00046   /// Flag to check if the timer is recurring.
00047   int recurring_timer_;
00048 };
00049 
00050 /**
00051  * @class ACE_Timer_Node_T
00052  *
00053  * @brief Maintains the state associated with a Timer entry.
00054  */
00055 template <class TYPE>
00056 class ACE_Timer_Node_T
00057 {
00058 public:
00059   /// Default constructor
00060   ACE_Timer_Node_T (void);
00061 
00062   /// Destructor
00063   ~ACE_Timer_Node_T (void);
00064 
00065   /// Useful typedef ..
00066   typedef ACE_Timer_Node_Dispatch_Info_T <TYPE> DISPATCH_INFO;
00067 
00068   /// Singly linked list
00069   void set (const TYPE &type,
00070             const void *a,
00071             const ACE_Time_Value &t,
00072             const ACE_Time_Value &i,
00073             ACE_Timer_Node_T<TYPE> *n,
00074             long timer_id);
00075 
00076   /// Doubly linked list version
00077   void set (const TYPE &type,
00078             const void *a,
00079             const ACE_Time_Value &t,
00080             const ACE_Time_Value &i,
00081             ACE_Timer_Node_T<TYPE> *p,
00082             ACE_Timer_Node_T<TYPE> *n,
00083             long timer_id);
00084 
00085   // = Accessors
00086 
00087   /// Get the type.
00088   TYPE &get_type (void);
00089 
00090   /// Set the type.
00091   void set_type (TYPE &type);
00092 
00093   /// Get the asynchronous completion token.
00094   const void *get_act (void);
00095 
00096   /// Set the asynchronous completion token.
00097   void set_act (void *act);
00098 
00099   /// Get the timer value.
00100   const ACE_Time_Value &get_timer_value (void) const;
00101 
00102   /// Set the timer value.
00103   void set_timer_value (const ACE_Time_Value &timer_value);
00104 
00105   /// Get the timer interval.
00106   const ACE_Time_Value &get_interval (void) const;
00107 
00108   /// Set the timer interval.
00109   void set_interval (const ACE_Time_Value &interval);
00110 
00111   /// Get the previous pointer.
00112   ACE_Timer_Node_T<TYPE> *get_prev (void);
00113 
00114   /// Set the previous pointer.
00115   void set_prev (ACE_Timer_Node_T<TYPE> *prev);
00116 
00117   /// Get the next pointer.
00118   ACE_Timer_Node_T<TYPE> *get_next (void);
00119 
00120   /// Set the next pointer.
00121   void set_next (ACE_Timer_Node_T<TYPE> *next);
00122 
00123   /// Get the timer_id.
00124   long get_timer_id (void) const;
00125 
00126   /// Set the timer_id.
00127   void set_timer_id (long timer_id);
00128 
00129   /// Get the dispatch info. The dispatch information is got
00130   /// through <info>. This form helps us in preventing allocation and
00131   /// deleting data along the criticl path.
00132   /// @@TODO: We may want to have a copying version too, so that our
00133   /// interface will be complete..
00134   void get_dispatch_info (ACE_Timer_Node_Dispatch_Info_T <TYPE> &info);
00135 
00136   /// Dump the state of an TYPE.
00137   void dump (void) const;
00138 
00139 private:
00140   /// Type of object stored in the Queue
00141   TYPE type_;
00142 
00143   /// Asynchronous completion token associated with the timer.
00144   const void *act_;
00145 
00146   /// Time until the timer expires.
00147   ACE_Time_Value timer_value_;
00148 
00149   /// If this is a periodic timer this holds the time until the next
00150   /// timeout.
00151   ACE_Time_Value interval_;
00152 
00153   /// Pointer to previous timer.
00154   ACE_Timer_Node_T<TYPE> *prev_;
00155 
00156   /// Pointer to next timer.
00157   ACE_Timer_Node_T<TYPE> *next_;
00158 
00159   /// Id of this timer (used to cancel timers before they expire).
00160   long timer_id_;
00161 };
00162 
00163 /**
00164  * @class ACE_Timer_Queue_Iterator_T
00165  *
00166  * @brief Generic interface for iterating over a subclass of
00167  * ACE_Timer_Queue.
00168  *
00169  * This is a generic iterator that can be used to visit every
00170  * node of a timer queue.  Be aware that it isn't guaranteed
00171  * that the transversal will be in order of timeout values.
00172  */
00173 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00174 class ACE_Timer_Queue_Iterator_T
00175 {
00176 public:
00177   // = Initialization and termination methods.
00178   /// Constructor.
00179   ACE_Timer_Queue_Iterator_T (void);
00180 
00181   /// Destructor.
00182   virtual ~ACE_Timer_Queue_Iterator_T (void);
00183 
00184   /// Positions the iterator at the earliest node in the Timer Queue
00185   virtual void first (void) = 0;
00186 
00187   /// Positions the iterator at the next node in the Timer Queue
00188   virtual void next (void) = 0;
00189 
00190   /// Returns true when there are no more nodes in the sequence
00191   virtual int isdone (void) const = 0;
00192 
00193   /// Returns the node at the current position in the sequence
00194   virtual ACE_Timer_Node_T<TYPE> *item (void) = 0;
00195 };
00196 
00197 /**
00198  * @class ACE_Timer_Queue_T
00199  *
00200  * @brief Provides an interface to timers.
00201  *
00202  * This is an abstract base class that provides hook for
00203  * implementing specialized policies such as ACE_Timer_List
00204  * and ACE_Timer_Heap.
00205  */
00206 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00207 class ACE_Timer_Queue_T
00208 {
00209 public:
00210   /// Type of Iterator.
00211   typedef ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> ITERATOR;
00212 
00213   // = Initialization and termination methods.
00214   /**
00215    * Default constructor. <upcall_functor> is the instance of the
00216    * FUNCTOR to be used by the queue. If <upcall_functor> is 0, Timer
00217    * Queue will create a default FUNCTOR.  <freelist> the freelist of
00218    * timer nodes.  If 0, then a default freelist will be created.
00219    */
00220   ACE_Timer_Queue_T (FUNCTOR *upcall_functor = 0,
00221                      ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
00222 
00223   /// Destructor - make virtual for proper destruction of inherited
00224   /// classes.
00225   virtual ~ACE_Timer_Queue_T (void);
00226 
00227   /// True if queue is empty, else false.
00228   virtual int is_empty (void) const = 0;
00229 
00230   /// Returns the time of the earlier node in the Timer_Queue.  Must
00231   /// be called on a non-empty queue.
00232   virtual const ACE_Time_Value &earliest_time (void) const = 0;
00233 
00234   /**
00235    * Schedule <type> that will expire at <future_time>, which is
00236    * specified in absolute time.  If it expires then <act> is passed
00237    * in as the value to the <functor>.  If <interval> is != to
00238    * <ACE_Time_Value::zero> then it is used to reschedule the <type>
00239    * automatically, using relative time to the current <gettimeofday>.
00240    * This method returns a <timer_id> that uniquely identifies the the
00241    * <type> entry in an internal list.  This <timer_id> can be used to
00242    * cancel the timer before it expires.  The cancellation ensures
00243    * that <timer_ids> are unique up to values of greater than 2
00244    * billion timers.  As long as timers don't stay around longer than
00245    * this there should be no problems with accidentally deleting the
00246    * wrong timer.  Returns -1 on failure (which is guaranteed never to
00247    * be a valid <timer_id>).
00248    */
00249   virtual long schedule (const TYPE &type,
00250                          const void *act,
00251                          const ACE_Time_Value &future_time,
00252                          const ACE_Time_Value &interval = ACE_Time_Value::zero);
00253 
00254   /**
00255    * Resets the interval of the timer represented by <timer_id> to
00256    * <interval>, which is specified in relative time to the current
00257    * <gettimeofday>.  If <interval> is equal to
00258    * <ACE_Time_Value::zero>, the timer will become a non-rescheduling
00259    * timer.  Returns 0 if successful, -1 if not.
00260    */
00261   virtual int reset_interval (long timer_id,
00262                               const ACE_Time_Value &interval) = 0;
00263 
00264   /**
00265    * Cancel all timer associated with <type>.  If
00266    * <dont_call_handle_close> is 0 then the <functor> will be invoked,
00267    * which typically invokes the <handle_close> hook.  Returns number
00268    * of timers cancelled.
00269    */
00270   virtual int cancel (const TYPE &type,
00271                       int dont_call_handle_close = 1) = 0;
00272 
00273   /**
00274    * Cancel the single timer that matches the <timer_id> value (which
00275    * was returned from the <schedule> method).  If act is non-NULL
00276    * then it will be set to point to the ``magic cookie'' argument
00277    * passed in when the timer was registered.  This makes it possible
00278    * to free up the memory and avoid memory leaks.  If
00279    * <dont_call_handle_close> is 0 then the <functor> will be invoked,
00280    * which typically calls the <handle_close> hook.  Returns 1 if
00281    * cancellation succeeded and 0 if the <timer_id> wasn't found.
00282    */
00283   virtual int cancel (long timer_id,
00284                       const void **act = 0,
00285                       int dont_call_handle_close = 1) = 0;
00286 
00287   /**
00288    * Run the <functor> for all timers whose values are <= <cur_time>.
00289    * This does not account for <timer_skew>.  Returns the number of
00290    * timers canceled.
00291    */
00292   virtual int expire (const ACE_Time_Value &current_time);
00293 
00294   /**
00295    * Get the dispatch information for a timer whose value is <= <cur_time>.
00296    * This does not account for <timer_skew>. Returns 1 if
00297    * there is a node whose value <= <cur_time> else returns a 0.
00298    *
00299    */
00300   virtual int dispatch_info (const ACE_Time_Value &current_time,
00301                              ACE_Timer_Node_Dispatch_Info_T<TYPE> &info);
00302 
00303   /**
00304    * Run the <functor> for all timers whose values are <=
00305    * <ACE_OS::gettimeofday>.  Also accounts for <timer_skew>.
00306    *
00307    * Depending on the resolution of the underlying OS the system calls
00308    * like select()/poll() might return at time different than that is
00309    * specified in the timeout. Suppose the OS guarantees a resolution of t ms.
00310    * The timeline will look like
00311    *
00312    *             A                   B
00313    *             |                   |
00314    *             V                   V
00315    *  |-------------|-------------|-------------|-------------|
00316    *  t             t             t             t             t
00317    *
00318    *
00319    * If you specify a timeout value of A, then the timeout will not occur
00320    * at A but at the next interval of the timer, which is later than
00321    * that is expected. Similarly, if your timeout value is equal to B,
00322    * then the timeout will occur at interval after B. Now depending upon the
00323    * resolution of your timeouts and the accuracy of the timeouts
00324    * needed for your application, you should set the value of
00325    * <timer_skew>. In the above case, if you want the timeout A to fire
00326    * no later than A, then you should specify your <timer_skew> to be
00327    * A % t.
00328    *
00329    * The timeout value should be specified via the macro ACE_TIMER_SKEW
00330    * in your config.h file. The default value is zero.
00331    *
00332    * Things get interesting if the t before the timeout value B is zero
00333    * i.e your timeout is less than the interval. In that case, you are
00334    * almost sure of not getting the desired timeout behaviour. Maybe you
00335    * should look for a better OS :-)
00336    *
00337    *  Returns the number of timers canceled.
00338    */
00339 
00340   /* virtual */ int expire (void);
00341 
00342   /**
00343    * Returns the current time of day.  This method allows different
00344    * implementations of the timer queue to use special high resolution
00345    * timers.
00346    */
00347   /* virtual */ ACE_Time_Value gettimeofday (void);
00348 
00349   /// Allows applications to control how the timer queue gets the time
00350   /// of day.
00351   void gettimeofday (ACE_Time_Value (*gettimeofday)(void));
00352 
00353   /// Determine the next event to timeout.  Returns <max> if there are
00354   /// no pending timers or if all pending timers are longer than max.
00355   /// This method acquires a lock internally since it modifies internal state.
00356   virtual ACE_Time_Value *calculate_timeout (ACE_Time_Value *max);
00357 
00358   /**
00359    * Determine the next event to timeout.  Returns <max> if there are
00360    * no pending timers or if all pending timers are longer than max.
00361    * <the_timeout> should be a pointer to storage for the timeout value,
00362    * and this value is also returned.  This method does not acquire a
00363    * lock internally since it doesn't modify internal state.  If you
00364    * need to call this method when the queue is being modified
00365    * concurrently, however, you should make sure to acquire the <mutex()>
00366    * externally before making the call.
00367    */
00368   virtual ACE_Time_Value *calculate_timeout (ACE_Time_Value *max,
00369                                              ACE_Time_Value *the_timeout);
00370 
00371   /// Set the timer skew for the Timer_Queue.
00372   void timer_skew (const ACE_Time_Value &skew);
00373 
00374   /// Get the timer skew for the Timer_Queue.
00375   const ACE_Time_Value &timer_skew (void) const;
00376 
00377   /// Synchronization variable used by the queue
00378   ACE_LOCK &mutex (void);
00379 
00380   /// Accessor to the upcall functor
00381   FUNCTOR &upcall_functor (void);
00382 
00383   /// Returns a pointer to this ACE_Timer_Queue's iterator.
00384   virtual ITERATOR &iter (void) = 0;
00385 
00386   /// Removes the earliest node from the queue and returns it
00387   virtual ACE_Timer_Node_T<TYPE> *remove_first (void) = 0;
00388 
00389   /// Dump the state of a object.
00390   virtual void dump (void) const;
00391 
00392   /// Reads the earliest node from the queue and returns it.
00393   virtual ACE_Timer_Node_T<TYPE> *get_first (void) = 0;
00394 
00395   /// Method used to return a timer node to the queue's ownership
00396   /// after it is returned by a method like <remove_first>.
00397   virtual void return_node (ACE_Timer_Node_T<TYPE> *);
00398 
00399   /// This method will call the preinvoke() on <functor>.
00400   void preinvoke (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info,
00401                   const ACE_Time_Value &cur_time,
00402                   const void *&upcall_act);
00403 
00404   /// This method will call the timeout() on <functor>.
00405   void upcall (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info,
00406                const ACE_Time_Value &cur_time);
00407 
00408   /// This method will call the postinvoke() on <functor>.
00409   void postinvoke (ACE_Timer_Node_Dispatch_Info_T<TYPE> &info,
00410                    const ACE_Time_Value &cur_time,
00411                    const void *upcall_act);
00412 
00413 protected:
00414 
00415   /// Schedule a timer.
00416   virtual long schedule_i (const TYPE &type,
00417                            const void *act,
00418                            const ACE_Time_Value &future_time,
00419                            const ACE_Time_Value &interval) = 0;
00420 
00421   /// Reschedule an "interval" <ACE_Timer_Node>.
00422   virtual void reschedule (ACE_Timer_Node_T<TYPE> *) = 0;
00423 
00424   /// Factory method that allocates a new node.
00425   virtual ACE_Timer_Node_T<TYPE> *alloc_node (void);
00426 
00427   /// Factory method that frees a previously allocated node.
00428   virtual void free_node (ACE_Timer_Node_T<TYPE> *);
00429 
00430   /// Non-locking version of dispatch_info ()
00431   virtual int dispatch_info_i (const ACE_Time_Value &current_time,
00432                                ACE_Timer_Node_Dispatch_Info_T<TYPE> &info);
00433 
00434   /// Synchronization variable for ACE_Timer_Queue.
00435   /// @note The right name would be lock_, but HP/C++ will choke on that!
00436   ACE_LOCK mutex_;
00437 
00438   /// Class that implements a free list
00439   ACE_Free_List<ACE_Timer_Node_T<TYPE> > *free_list_;
00440 
00441   /// Pointer to function that returns the current time of day.
00442   ACE_Time_Value (*gettimeofday_)(void);
00443 
00444   /// Upcall functor
00445   FUNCTOR *upcall_functor_;
00446 
00447   /// To delete or not to delete is the question?
00448   int delete_upcall_functor_;
00449 
00450   /// Flag to delete only if the class created the <free_list_>
00451   int delete_free_list_;
00452 
00453 private:
00454 
00455   /// Returned by <calculate_timeout>.
00456   ACE_Time_Value timeout_;
00457 
00458   /// Adjusts for timer skew in various clocks.
00459   ACE_Time_Value timer_skew_;
00460 
00461   // = Don't allow these operations for now.
00462   ACE_UNIMPLEMENTED_FUNC (ACE_Timer_Queue_T (const ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> &))
00463   ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> &))
00464 };
00465 
00466 /**
00467  * @class ACE_Event_Handler_Handle_Timeout_Upcall
00468  *
00469  * @brief Functor for Timer_Queues.
00470  *
00471  * This class implements the functor required by the Timer
00472  * Queue to call <handle_timeout> on ACE_Event_Handlers.
00473  */
00474 template <class ACE_LOCK>
00475 class ACE_Event_Handler_Handle_Timeout_Upcall
00476 {
00477 public:
00478   typedef ACE_Timer_Queue_T<ACE_Event_Handler *,
00479                             ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK>,
00480                             ACE_LOCK>
00481           TIMER_QUEUE;
00482 
00483   // = Initialization and termination methods.
00484   /// Constructor.
00485   ACE_Event_Handler_Handle_Timeout_Upcall (void);
00486 
00487   /// Destructor.
00488   ~ACE_Event_Handler_Handle_Timeout_Upcall (void);
00489 
00490   /// This method is called when a timer is registered.
00491   int registration (TIMER_QUEUE &timer_queue,
00492                     ACE_Event_Handler *handler,
00493                     const void *arg);
00494 
00495   /// This method is called before the timer expires.
00496   int preinvoke (TIMER_QUEUE &timer_queue,
00497                  ACE_Event_Handler *handler,
00498                  const void *arg,
00499                  int recurring_timer,
00500                  const ACE_Time_Value &cur_time,
00501                  const void *&upcall_act);
00502 
00503   /// This method is called when the timer expires.
00504   int timeout (TIMER_QUEUE &timer_queue,
00505                ACE_Event_Handler *handler,
00506                const void *arg,
00507                int recurring_timer,
00508                const ACE_Time_Value &cur_time);
00509 
00510   /// This method is called after the timer expires.
00511   int postinvoke (TIMER_QUEUE &timer_queue,
00512                   ACE_Event_Handler *handler,
00513                   const void *arg,
00514                   int recurring_timer,
00515                   const ACE_Time_Value &cur_time,
00516                   const void *upcall_act);
00517 
00518   /// This method is called when a handler is cancelled
00519   int cancel_type (TIMER_QUEUE &timer_queue,
00520                    ACE_Event_Handler *handler,
00521                    int dont_call,
00522                    int &requires_reference_counting);
00523 
00524   /// This method is called when a timer is cancelled
00525   int cancel_timer (TIMER_QUEUE &timer_queue,
00526                     ACE_Event_Handler *handler,
00527                     int dont_call,
00528                     int requires_reference_counting);
00529 
00530   /// This method is called when the timer queue is destroyed and
00531   /// the timer is still contained in it
00532   int deletion (TIMER_QUEUE &timer_queue,
00533                 ACE_Event_Handler *handler,
00534                 const void *arg);
00535 
00536 private:
00537 
00538   /// Flag indicating that reference counting is required for this
00539   /// event handler upcall.
00540   int requires_reference_counting_;
00541 
00542   // = Don't allow these operations for now.
00543   ACE_UNIMPLEMENTED_FUNC (ACE_Event_Handler_Handle_Timeout_Upcall (const ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK> &))
00544   ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Event_Handler_Handle_Timeout_Upcall<ACE_LOCK> &))
00545 };
00546 
00547 ACE_END_VERSIONED_NAMESPACE_DECL
00548 
00549 #if defined (__ACE_INLINE__)
00550 #include "ace/Timer_Queue_T.inl"
00551 #endif /* __ACE_INLINE__ */
00552 
00553 #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) && !defined (ACE_HAS_BROKEN_HPUX_TEMPLATES)
00554 #include "ace/Timer_Queue_T.cpp"
00555 #endif /* ACE_TEMPLATES_REQUIRE_SOURCE && !ACE_HAS_BROKEN_HPUX_TEMPLATES */
00556 
00557 #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
00558 #pragma implementation ("Timer_Queue_T.cpp")
00559 #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
00560 
00561 #include /**/ "ace/post.h"
00562 #endif /* ACE_TIMER_QUEUE_T_H */

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