Timer_Heap_T.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 //=============================================================================
00004 /**
00005  *  @file    Timer_Heap_T.h
00006  *
00007  *  Timer_Heap_T.h,v 4.51 2006/04/27 11:17:56 jwillemsen Exp
00008  *
00009  *  @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
00010  */
00011 //=============================================================================
00012 
00013 #ifndef ACE_TIMER_HEAP_T_H
00014 #define ACE_TIMER_HEAP_T_H
00015 #include /**/ "ace/pre.h"
00016 
00017 #include "ace/Timer_Queue_T.h"
00018 
00019 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00020 # pragma once
00021 #endif /* ACE_LACKS_PRAGMA_ONCE */
00022 
00023 #include "ace/Free_List.h"
00024 #include "ace/Unbounded_Set.h"
00025 
00026 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00027 
00028 // Forward declaration
00029 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00030 class ACE_Timer_Heap_T;
00031 
00032 /**
00033  * @class ACE_Timer_Heap_Iterator_T
00034  *
00035  * @brief Iterates over an <ACE_Timer_Heap_T>.
00036  *
00037  * This is a generic iterator that can be used to visit every
00038  * node of a timer queue.  Be aware that it doesn't transverse
00039  * in the order of timeout values.
00040  */
00041 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00042 class ACE_Timer_Heap_Iterator_T : public ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>
00043 {
00044 public:
00045   /// Constructor.
00046   ACE_Timer_Heap_Iterator_T (ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK> &);
00047 
00048   /// Destructor.
00049   ~ACE_Timer_Heap_Iterator_T (void);
00050 
00051   /// Positions the iterator at the earliest node in the Timer Queue
00052   virtual void first (void);
00053 
00054   /// Positions the iterator at the next node in the Timer Queue
00055   virtual void next (void);
00056 
00057   /// Returns true when there are no more nodes in the sequence
00058   virtual int isdone (void) const;
00059 
00060   /// Returns the node at the current position in the sequence
00061   virtual ACE_Timer_Node_T<TYPE> *item (void);
00062 
00063 protected:
00064   /// Pointer to the ACE_Timer_Heap that we are iterating over.
00065   ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK> &timer_heap_;
00066 
00067   /// Position in the array where the iterator is at
00068   size_t position_;
00069 };
00070 
00071 /**
00072  * @class ACE_Timer_Heap_T
00073  *
00074  * @brief Provides a very fast and predictable timer implementation.
00075  *
00076  * This implementation uses a heap-based callout queue of
00077  * absolute times.  Therefore, in the average and worst case,
00078  * scheduling, canceling, and expiring timers is O(log N) (where
00079  * N is the total number of timers).  In addition, we can also
00080  * preallocate as many @c ACE_Timer_Node objects as there are slots
00081  * in the heap.  This allows us to completely remove the need for
00082  * dynamic memory allocation, which is important for real-time
00083  * systems.
00084  */
00085 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00086 class ACE_Timer_Heap_T : public ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK>
00087 {
00088 public:
00089   typedef ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> HEAP_ITERATOR;
00090   friend class ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>;
00091 
00092   typedef ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> INHERITED;
00093 
00094   // = Initialization and termination methods.
00095   /**
00096    * The Constructor creates a heap with specified number of elements.
00097    * This can also take in a upcall functor and freelist (if 0, then
00098    * defaults will be created).
00099    *
00100    * @param size The maximum number of timers that can be
00101    * inserted into the new object.
00102    * @param preallocated Default 0, if non-0 then all the memory
00103    * for the @c ACE_Timer_Node objects will be pre-allocated. This saves
00104    * time and is more predictable (though it requires more space).
00105    * Otherwise, timer nodes are allocated as needed.
00106    * @param freelist is the freelist of timer nodes.
00107    * @param upcall_functor If 0 Timer Heap will create a default FUNCTOR.
00108    */
00109   ACE_Timer_Heap_T (size_t size,
00110                     int preallocated = 0,
00111                     FUNCTOR *upcall_functor = 0,
00112                     ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
00113 
00114   /**
00115    * Default constructor. @c upcall_functor is the instance of the
00116    * FUNCTOR to be used by the queue. If @c upcall_functor is 0, Timer
00117    * Heap will create a default FUNCTOR.  @c freelist is the freelist of
00118    * timer nodes.  If 0, then a default freelist will be created.  The default
00119    * size will be ACE_DEFAULT_TIMERS and there will be no preallocation.
00120    */
00121   ACE_Timer_Heap_T (FUNCTOR *upcall_functor = 0,
00122                     ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
00123 
00124   /// Destructor.
00125   virtual ~ACE_Timer_Heap_T (void);
00126 
00127   /// True if heap is empty, else false.
00128   virtual int is_empty (void) const;
00129 
00130   /// Returns the time of the earliest node in the Timer_Queue.
00131   /// Must be called on a non-empty queue.
00132   virtual const ACE_Time_Value &earliest_time (void) const;
00133 
00134   /**
00135    * Resets the interval of the timer represented by <timer_id> to
00136    * <interval>, which is specified in relative time to the current
00137    * <gettimeofday>.  If <interval> is equal to
00138    * <ACE_Time_Value::zero>, the timer will become a non-rescheduling
00139    * timer.  Returns 0 if successful, -1 if not.
00140    */
00141   virtual int reset_interval (long timer_id,
00142                               const ACE_Time_Value &interval);
00143 
00144   /**
00145    * Cancel all timers associated with <type>.  If <dont_call> is 0
00146    * then the <functor> will be invoked.  Returns number of timers
00147    * cancelled.
00148    */
00149   virtual int cancel (const TYPE &type,
00150                       int dont_call_handle_close = 1);
00151 
00152   /**
00153    * Cancel the single timer that matches the <timer_id> value (which
00154    * was returned from the <schedule> method).  If act is non-NULL
00155    * then it will be set to point to the ``magic cookie'' argument
00156    * passed in when the timer was registered.  This makes it possible
00157    * to free up the memory and avoid memory leaks.  If <dont_call> is
00158    * 0 then the <functor> will be invoked.  Returns 1 if cancellation
00159    * succeeded and 0 if the <timer_id> wasn't found.
00160    */
00161   virtual int cancel (long timer_id,
00162                       const void **act = 0,
00163                       int dont_call_handle_close = 1);
00164 
00165   /// Returns a pointer to this ACE_Timer_Queue's iterator.
00166   virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> &iter (void);
00167 
00168   /**
00169    * Removes the earliest node from the queue and returns it. Note that
00170    * the timer is removed from the heap, but is not freed, and its ID
00171    * is not reclaimed. The caller is responsible for calling either
00172    * @c reschedule() or @c free_node() after this function returns. Thus,
00173    * this function is for support of @c ACE_Timer_Queue::expire and
00174    * should not be used unadvisedly in other conditions.
00175    */
00176   ACE_Timer_Node_T <TYPE> *remove_first (void);
00177 
00178   /// Dump the state of an object.
00179   virtual void dump (void) const;
00180 
00181   /// Reads the earliest node from the queue and returns it.
00182   virtual ACE_Timer_Node_T<TYPE> *get_first (void);
00183 
00184 protected:
00185 
00186   /**
00187    * Schedule a timer that may optionally auto-reset.
00188    * Schedule <type> that will expire at <future_time>,
00189    * which is specified in absolute time.  If it expires then <act> is
00190    * passed in as the value to the <functor>.  If <interval> is != to
00191    * <ACE_Time_Value::zero> then it is used to reschedule the <type>
00192    * automatically, using relative time to the current <gettimeofday>.
00193    * This method returns a <timer_id> that uniquely identifies the the
00194    * <type> entry in an internal list.  This <timer_id> can be used to
00195    * cancel the timer before it expires.  The cancellation ensures
00196    * that <timer_ids> are unique up to values of greater than 2
00197    * billion timers.  As long as timers don't stay around longer than
00198    * this there should be no problems with accidentally deleting the
00199    * wrong timer.  Returns -1 on failure (which is guaranteed never to
00200    * be a valid <timer_id>).
00201    */
00202   virtual long schedule_i (const TYPE &type,
00203                            const void *act,
00204                            const ACE_Time_Value &future_time,
00205                            const ACE_Time_Value &interval);
00206 
00207   /// Reschedule an "interval" <ACE_Timer_Node>.
00208   virtual void reschedule (ACE_Timer_Node_T<TYPE> *);
00209 
00210   /// Factory method that allocates a new node (uses operator new if
00211   /// we're *not* preallocating, otherwise uses an internal freelist).
00212   virtual ACE_Timer_Node_T<TYPE> *alloc_node (void);
00213 
00214   /**
00215    * Factory method that frees a previously allocated node (uses
00216    * operator delete if we're *not* preallocating, otherwise uses an
00217    * internal freelist).
00218    */
00219   virtual void free_node (ACE_Timer_Node_T<TYPE> *);
00220 
00221 private:
00222   /// Remove and return the <slot>th <ACE_Timer_Node> and restore the
00223   /// heap property.
00224   ACE_Timer_Node_T<TYPE> *remove (size_t slot);
00225 
00226   /// Insert @a new_node into the heap and restore the heap property.
00227   void insert (ACE_Timer_Node_T<TYPE> *new_node);
00228 
00229   /**
00230    * Doubles the size of the heap and the corresponding timer_ids array.
00231    * If preallocation is used, will also double the size of the
00232    * preallocated array of ACE_Timer_Nodes.
00233    */
00234   void grow_heap (void);
00235 
00236   /// Restore the heap property, starting at <slot>.
00237   void reheap_up (ACE_Timer_Node_T<TYPE> *new_node,
00238                   size_t slot,
00239                   size_t parent);
00240 
00241   /// Restore the heap property, starting at <slot>.
00242   void reheap_down (ACE_Timer_Node_T<TYPE> *moved_node,
00243                     size_t slot,
00244                     size_t child);
00245 
00246   /// Copy <moved_node> into the <slot> slot of <heap_> and move
00247   /// <slot> into the corresponding slot in the <timer_id_> array.
00248   void copy (size_t slot, ACE_Timer_Node_T<TYPE> *moved_node);
00249 
00250   /**
00251    * Returns a timer id that uniquely identifies this timer.  This id
00252    * can be used to cancel a timer via the <cancel (int)> method.  The
00253    * timer id returned from this method will never == -1 to avoid
00254    * conflicts with other failure return values.
00255    */
00256   long timer_id (void);
00257 
00258   /// Pops and returns a new timer id from the freelist.
00259   long pop_freelist (void);
00260 
00261   /// Pushes <old_id> onto the freelist.
00262   void push_freelist (long old_id);
00263 
00264   /// Maximum size of the heap.
00265   size_t max_size_;
00266 
00267   /// Current size of the heap.
00268   size_t cur_size_;
00269 
00270   /// Number of heap entries in transition (removed from the queue, but
00271   /// not freed) and may be rescheduled or freed.
00272   size_t cur_limbo_;
00273 
00274   /// Iterator used to expire timers.
00275   HEAP_ITERATOR *iterator_;
00276 
00277   /**
00278    * Current contents of the Heap, which is organized as a "heap" of
00279    * <ACE_Timer_Node> *'s.  In this context, a heap is a "partially
00280    * ordered, almost complete" binary tree, which is stored in an
00281    * array.
00282    */
00283   ACE_Timer_Node_T<TYPE> **heap_;
00284 
00285   /**
00286    * An array of "pointers" that allows each <ACE_Timer_Node> in the
00287    * <heap_> to be located in O(1) time.  Basically, <timer_id_[i]>
00288    * contains the slot in the <heap_> array where an <ACE_Timer_Node>
00289    * * with timer id <i> resides.  Thus, the timer id passed back from
00290    * <schedule> is really a slot into the <timer_ids> array.  The
00291    * <timer_ids_> array serves two purposes: negative values are
00292    * indications of free timer IDs, whereas positive values are
00293    * "pointers" into the <heap_> array for assigned timer IDs.
00294    */
00295   ssize_t *timer_ids_;
00296 
00297   /// "Pointer" to the element in the <timer_ids_> array that was
00298   /// last given out as a timer ID.
00299   size_t timer_ids_curr_;
00300 
00301   /// Index representing the lowest timer ID that has been freed. When
00302   /// the timer_ids_next_ value wraps around, it starts back at this
00303   /// point.
00304   size_t timer_ids_min_free_;
00305 
00306   /**
00307    * If this is non-0, then we preallocate <max_size_> number of
00308    * <ACE_Timer_Node> objects in order to reduce dynamic allocation
00309    * costs.  In auto-growing implementation, this points to the
00310    * last array of nodes allocated.
00311    */
00312   ACE_Timer_Node_T<TYPE> *preallocated_nodes_;
00313 
00314   /// This points to the head of the <preallocated_nodes_> freelist,
00315   /// which is organized as a stack.
00316   ACE_Timer_Node_T<TYPE> *preallocated_nodes_freelist_;
00317 
00318   /// Set of pointers to the arrays of preallocated timer nodes.
00319   /// Used to delete the allocated memory when required.
00320   ACE_Unbounded_Set<ACE_Timer_Node_T<TYPE> *> preallocated_node_set_;
00321 
00322   // = Don't allow these operations for now.
00323   ACE_UNIMPLEMENTED_FUNC (ACE_Timer_Heap_T (const ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK> &))
00324   ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK> &))
00325 };
00326 
00327 ACE_END_VERSIONED_NAMESPACE_DECL
00328 
00329 #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) && !defined(ACE_HAS_BROKEN_HPUX_TEMPLATES)
00330 #include "ace/Timer_Heap_T.cpp"
00331 #endif /* ACE_TEMPLATES_REQUIRE_SOURCE && !ACE_HAS_BROKEN_HPUX_TEMPLATES */
00332 
00333 #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
00334 #pragma implementation ("Timer_Heap_T.cpp")
00335 #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
00336 
00337 #include /**/ "ace/post.h"
00338 #endif /* ACE_TIMER_HEAP_T_H */

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