summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrunsch <brunsch@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1997-06-04 00:28:45 +0000
committerbrunsch <brunsch@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1997-06-04 00:28:45 +0000
commit1e92c1984331cacea0b72d9d817f28b8dacdc218 (patch)
treedf56cae7425595d3da052496955161fadc6bc852
parent35d1135d0091ec71142a95fdbc7c3a3bb741ebec (diff)
downloadATCD-1e92c1984331cacea0b72d9d817f28b8dacdc218.tar.gz
*** empty log message ***
-rw-r--r--ChangeLog-97a114
-rw-r--r--ace/Free_List.cpp105
-rw-r--r--ace/Free_List.h134
-rw-r--r--ace/Free_List.i65
-rw-r--r--ace/OS.h12
-rw-r--r--ace/Proactor.cpp13
-rw-r--r--ace/Proactor.h7
-rw-r--r--ace/Timer_Hash.h64
-rw-r--r--ace/Timer_Hash_T.cpp482
-rw-r--r--ace/Timer_Hash_T.h234
-rw-r--r--ace/Timer_Heap.h4
-rw-r--r--ace/Timer_Heap_T.cpp222
-rw-r--r--ace/Timer_Heap_T.h78
-rw-r--r--ace/Timer_List.h4
-rw-r--r--ace/Timer_List_T.cpp322
-rw-r--r--ace/Timer_List_T.h63
-rw-r--r--ace/Timer_Queue.cpp39
-rw-r--r--ace/Timer_Queue.h31
-rw-r--r--ace/Timer_Queue.i22
-rw-r--r--ace/Timer_Queue_T.cpp121
-rw-r--r--ace/Timer_Queue_T.h189
-rw-r--r--ace/Timer_Queue_T.i134
-rw-r--r--ace/Timer_Wheel.h4
-rw-r--r--ace/Timer_Wheel_T.cpp539
-rw-r--r--ace/Timer_Wheel_T.h117
-rw-r--r--tests/Timer_Queue_Test.cpp271
26 files changed, 2601 insertions, 789 deletions
diff --git a/ChangeLog-97a b/ChangeLog-97a
index 239f046aeb5..6efff97c981 100644
--- a/ChangeLog-97a
+++ b/ChangeLog-97a
@@ -1,3 +1,117 @@
+Tue Jun 3 18:16:02 1997 Darrell Brunsch <brunsch@cs.wustl.edu>
+
+ * ace/Timer_Queue.*:
+
+ Templatized ACE_Event_Handler_Handle_Timeout_Upcall with LOCK
+
+ Added deletion() to Upcall Functors. This gets called if there
+ are any nodes in a queue and the queue's destructor is called
+
+ * ace/Timer_Queue_T.*:
+
+ Changed iterator accessor to public
+
+ Removed two template parameters from ACE_Timer_Node_T so only
+ EVENT is left. Added accessors instead of using friendships, and
+ deleted the constructor (use set() instead)
+
+ Changed iterator into a general iterator (with first(), next(),
+ isdone() and item () methods)
+
+ Added remove_first () method that removes and returns the earliest
+ timer in the queue
+
+ Added ACE_Free_List support
+
+ * ace/Timer_Heap*:
+
+ Added upcall functor deletion() support
+
+ Added remove_first () method that removes and returns the earliest
+ timer in the queue
+
+ * ace/Timer_List*:
+
+ Changed to double-linked circular list and changed the timer_id to
+ be a pointer to the node (like it is in Timer Wheel and Timer Hash)
+
+ Added upcall functor deletion() support
+
+ Added remove_first () method that removes and returns the earliest
+ timer in the queue
+
+ Added check for timer_id of -1 so we don't try to delete the error
+ code if it is passed into cancel
+
+ Changed Timer_List_Iterator_T constructor parameter from list to
+ listParm to resolve a conflict with STL. Thanks to Todd Barkalow
+ <barkate@louisville.stortek.com> for this fix
+
+ * ace/Timer_Wheel*:
+
+ Added HighRes timer support
+
+ Added upcall functor deletion() support
+
+ Added earliest_pos_ variable to keep track of the list with the
+ earliest node
+
+ Created an expire that is specialized for ACE_Timer_Wheel
+
+ Added remove_first () method that removes and returns the earliest
+ timer in the queue
+
+ Added check for timer_id of -1 so we don't try to delete the error
+ code if it is passed into cancel
+
+ * ace/Timer_Hash*:
+
+ Added Timer Hash Queue - This is a class that can take another
+ timer queue type (Timer List, Timer Heap...) as a template
+ parameter (BUCKET) and then do an intermediate hash of a timer to
+ determine which queue among a table of timer queues to put the
+ timer into. ACE_Timer_Hash is typedefed to the Timer List version
+ and ACE_Timer_Hash_Heap is typedefed to the Timer Heap version
+
+ Added HighRes timer support
+
+ Added upcall functor deletion() support
+
+ Created an expire that is specialized for ACE_Timer_Hash
+
+ Added remove_first () method that removes and returns the earliest
+ timer in the queue
+
+ Added check for timer_id of -1 so we don't try to delete the error
+ code if it is passed into cancel
+
+ * ace/Free_List.*
+
+ Added ACE_Free_List<T> and ACE_Locked_Free_List<T, LOCK>. These
+ are used to maintain free lists of nodes. ACE_Free_List is a
+ abstract class where ACE_Locked_Free_List is a concrete one that
+ has a mutex parameter (LOCK).
+
+ * ace/OS.h:
+
+ Added ACE_DEFAULT_TIMER_HASH_TABLE_SIZE constant
+
+ Added ACE_DEFAULT_FREE_LIST_* constants
+
+ * ace/Proactor.*:
+
+ Added deletion() to Upcall Functors. This gets called if there
+ are any nodes in a queue and the queue's destructor is called.
+
+ * tests/Timer_Queue_Test.cpp:
+
+ Added HighRes timer support
+
+ Changed the array of timer queues into a list (to more easily
+ add/remove/comment out an entry)
+
+ Added some more performance tests with randomization
+
Tue Jun 3 00:26:06 1997 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu>
* ace/OS.h: Changed the access protection for ACE_cond_t,
diff --git a/ace/Free_List.cpp b/ace/Free_List.cpp
new file mode 100644
index 00000000000..746aff21a41
--- /dev/null
+++ b/ace/Free_List.cpp
@@ -0,0 +1,105 @@
+#if !defined (ACE_FREE_LIST_C)
+#define ACE_FREE_LIST_C
+
+#include "ace/Free_List.h"
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Free_List.i"
+#endif /* __ACE_INLINE__ */
+
+// Empty constructor
+
+template <class T>
+ACE_Free_List<T>::~ACE_Free_List (void)
+{
+ // Nothing
+}
+
+
+// Default constructor that takes in a preallocation number (<prealloc>), a
+// low and high water mark (<lwm> and <hwm>) and an increment value (<inc>)
+
+template <class T, class LOCK>
+ACE_Locked_Free_List<T, LOCK>::ACE_Locked_Free_List (size_t prealloc,
+ size_t lwm,
+ size_t hwm,
+ size_t inc,
+ LOCK *mutex)
+ : free_list_ (NULL),
+ lwm_ (lwm),
+ hwm_ (hwm),
+ inc_ (inc),
+ size_ (0),
+ mutex_ (mutex == 0 ? new LOCK : mutex),
+ delete_mutex_ (mutex == 0)
+{
+ this->alloc (prealloc);
+}
+
+
+// Destructor - removes all the elements from the free_list
+
+template <class T, class LOCK>
+ACE_Locked_Free_List<T, LOCK>::~ACE_Locked_Free_List (void)
+{
+ while (this->free_list_ != NULL)
+ {
+ T *temp = this->free_list_;
+ this->free_list_ = this->free_list_->get_next ();
+ delete temp;
+ }
+
+ if (this->delete_mutex_)
+ delete this->mutex_;
+}
+
+
+// Allocates <n> extra nodes for the freelist
+
+template <class T, class LOCK> void
+ACE_Locked_Free_List<T, LOCK>::alloc (size_t n)
+{
+ ACE_MT (ACE_GUARD (LOCK, ace_mon, *this->mutex_));
+ for (;n > 0; n--, this->size_++)
+ {
+ T *temp;
+ ACE_NEW (temp, T);
+ temp->set_next (this->free_list_);
+ this->free_list_ = temp;
+ }
+}
+
+
+// Removes and frees <n> nodes from the freelist
+
+template <class T, class LOCK> void
+ACE_Locked_Free_List<T, LOCK>::dealloc (size_t n)
+{
+ ACE_MT (ACE_GUARD (LOCK, ace_mon, *this->mutex_));
+ for (;this->free_list_ != NULL && n > 0; this->size_--, n--)
+ {
+ T *temp = this->free_list_;
+ this->free_list_ = this->free_list_->get_next ();
+ delete temp;
+ }
+}
+
+
+// returns a reference to the mutex
+template <class T, class LOCK> LOCK &
+ACE_Locked_Free_List<T, LOCK>::get_mutex (void)
+{
+ return *this->mutex_;
+}
+
+template <class T, class LOCK> void
+ACE_Locked_Free_List<T, LOCK>::set_mutex (LOCK &mutex)
+{
+ if (this->delete_mutex_)
+ delete this->mutex_;
+
+ this->mutex_ = &mutex;
+ this->delete_mutex_ = 0;
+}
+
+#endif /* ACE_FREE_LIST_C */
diff --git a/ace/Free_List.h b/ace/Free_List.h
new file mode 100644
index 00000000000..c30fe9e23a5
--- /dev/null
+++ b/ace/Free_List.h
@@ -0,0 +1,134 @@
+/* -*- C++ -*- */
+
+// ============================================================================
+//
+// = LIBRARY
+// ace
+//
+// = FILENAME
+// Free_List.h
+//
+// = AUTHOR
+// Darrell Brunsch (brunsch@cs.wustl.edu)
+//
+// ============================================================================
+
+#if !defined(ACE_FREE_LIST_H)
+#define ACE_FREE_LIST_H
+
+#include "ace/OS.h"
+
+template <class T>
+class ACE_Free_List
+ // = TITLE
+ // Implements a free list
+ //
+ // = DESCRIPTION
+ // This class maintains a free list of nodes of type T.
+{
+public:
+ virtual ~ACE_Free_List (void) = 0;
+ // Destructor - removes all the elements from the free_list
+
+ virtual void add (T *element) = 0;
+ // Inserts an element onto the free list (if it isn't past the high water mark)
+
+ virtual T *remove (void) = 0;
+ // Takes a element off the freelist and returns it. It creates <inc> new elements
+ // if the size is at or below the low water mark.
+
+ virtual size_t size () = 0;
+ // Returns the current size of the free list
+
+ virtual void resize (size_t newsize) = 0;
+ // Resizes the free list to <newsize>
+};
+
+template <class T, class LOCK>
+class ACE_Locked_Free_List : public ACE_Free_List<T>
+ // = TITLE
+ // Implements a free list
+ //
+ // = DESCRIPTION
+ // This class maintains a free list of nodes of type T. It depends on
+ // the type T having a get_next () and set_next () method. It maintains
+ // a mutex so the freelist can be used in a multithreaded program .
+{
+public:
+ ACE_Locked_Free_List (size_t prealloc = ACE_DEFAULT_FREE_LIST_PREALLOC,
+ size_t lwm = ACE_DEFAULT_FREE_LIST_LWM,
+ size_t hwm = ACE_DEFAULT_FREE_LIST_HWM,
+ size_t inc = ACE_DEFAULT_FREE_LIST_INC,
+ LOCK *mutex = 0);
+ // Default constructor that takes in a preallocation number (<prealloc>), a
+ // low and high water mark (<lwm> and <hwm>) and an increment value (<inc>)
+
+ virtual ~ACE_Locked_Free_List (void);
+ // Destructor - removes all the elements from the free_list
+
+ virtual void add (T *element);
+ // Inserts an element onto the free list (if it isn't past the high water mark)
+
+ virtual T *remove (void);
+ // Takes a element off the freelist and returns it. It creates <inc> new elements
+ // if the size is at or below the low water mark.
+
+ virtual size_t size ();
+ // Returns the current size of the free list
+
+ virtual void resize (size_t newsize);
+ // Resizes the free list to <newsize>
+
+ LOCK &get_mutex (void);
+ // Returns a reference to the mutex
+
+ void set_mutex (LOCK &mutex);
+ // Sets the mutex to <mutex>
+
+protected:
+ virtual void alloc (size_t n);
+ // Allocates <n> extra nodes for the freelist
+
+ virtual void dealloc (size_t n);
+ // Removes and frees <n> nodes from the freelist
+
+ T *free_list_;
+ // Pointer to the first node in the freelist
+
+ size_t lwm_;
+ // Low water mark
+
+ size_t hwm_;
+ // High water mark
+
+ size_t inc_;
+ // Increment value
+
+ size_t size_;
+ // Keeps track of the size of the list
+
+ LOCK *mutex_;
+ // Synchronization variable for <ACE_Timer_Queue>.
+
+ int delete_mutex_;
+ // flag to remember ownership of the mutex
+
+private:
+ // = Don't allow these operations for now.
+ ACE_Locked_Free_List (const ACE_Locked_Free_List<T, LOCK> &);
+ void operator= (const ACE_Locked_Free_List<T, LOCK> &);
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Free_List.i"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Free_List.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Free_List.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* ACE_FREE_LIST_H */
diff --git a/ace/Free_List.i b/ace/Free_List.i
new file mode 100644
index 00000000000..e9447fe4ba5
--- /dev/null
+++ b/ace/Free_List.i
@@ -0,0 +1,65 @@
+/* -*- C++ -*- */
+
+// Inserts an element onto the free list (if it isn't past the high water mark)
+
+template <class T, class LOCK> ACE_INLINE void
+ACE_Locked_Free_List<T, LOCK>::add (T *element)
+{
+ ACE_MT (ACE_GUARD (LOCK, ace_mon, *this->mutex_));
+ // Check to see that we not at the high water mark
+ if (this->size_ >= this->hwm_)
+ {
+ element->set_next (this->free_list_);
+ this->free_list_ = element;
+ this->size_++;
+ }
+ else
+ delete element;
+}
+
+
+// Takes a element off the freelist and returns it. It creates <inc> new elements
+// if the size is at the low water mark.
+
+template <class T, class LOCK> ACE_INLINE T *
+ACE_Locked_Free_List<T, LOCK>::remove (void)
+{
+ ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, *this->mutex_, 0));
+ T *temp;
+
+ // If we are at the low water mark, add some nodes
+ if (this->size_ <= this->lwm_)
+ this->alloc (this->inc_);
+
+ // Remove a node
+ temp = this->free_list_;
+ this->free_list_ = this->free_list_->get_next ();
+ this->size_--;
+
+ return temp;
+}
+
+
+// Returns the current size of the free list
+
+template <class T, class LOCK> ACE_INLINE size_t
+ACE_Locked_Free_List<T, LOCK>::size ()
+{
+ return this->size_;
+}
+
+
+// Resizes the free list to <newsize>
+
+template <class T, class LOCK> ACE_INLINE void
+ACE_Locked_Free_List<T, LOCK>::resize (size_t newsize)
+{
+ ACE_MT (ACE_GUARD (LOCK, ace_mon, *this->mutex_));
+ // Check to see if we grow or shrink
+ if (newsize < this->size_)
+ this->dealloc (this->size_ - newsize);
+ else
+ this->alloc (newsize - this->size_);
+}
+
+
diff --git a/ace/OS.h b/ace/OS.h
index 189f6487092..53f031d4793 100644
--- a/ace/OS.h
+++ b/ace/OS.h
@@ -1,5 +1,4 @@
/* -*- C++ -*- */
-// $Id$
// ============================================================================
//
@@ -121,7 +120,16 @@
// Defaults for ACE Timer Wheel
#define ACE_DEFAULT_TIMER_WHEEL_SIZE 1024
-#define ACE_DEFAULT_TIMER_WHEEL_RESOLUTION 1000
+#define ACE_DEFAULT_TIMER_WHEEL_RESOLUTION 100
+
+// Default size for ACE Timer Hash table
+#define ACE_DEFAULT_TIMER_HASH_TABLE_SIZE 1024
+
+// Defaults for the ACE Free List
+#define ACE_DEFAULT_FREE_LIST_PREALLOC 0
+#define ACE_DEFAULT_FREE_LIST_LWM 0
+#define ACE_DEFAULT_FREE_LIST_HWM 25000
+#define ACE_DEFAULT_FREE_LIST_INC 100
// Here are all ACE-specific global declarations needed throughout
// ACE.
diff --git a/ace/Proactor.cpp b/ace/Proactor.cpp
index 202a0351099..5d3c3f15500 100644
--- a/ace/Proactor.cpp
+++ b/ace/Proactor.cpp
@@ -161,6 +161,19 @@ ACE_Proactor_Handle_Timeout_Upcall::cancellation (TIMER_QUEUE &timer_queue,
return 0;
}
+int
+ACE_Proactor_Handle_Timeout_Upcall::deletion (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler,
+ const void *arg)
+{
+ ACE_UNUSED_ARG (timer_queue);
+ ACE_UNUSED_ARG (handler);
+ ACE_UNUSED_ARG (arg);
+
+ // Do nothing
+ return 0;
+}
+
int
ACE_Proactor_Handle_Timeout_Upcall::proactor (ACE_Proactor &proactor)
{
diff --git a/ace/Proactor.h b/ace/Proactor.h
index 45b1b27c472..bab67676b14 100644
--- a/ace/Proactor.h
+++ b/ace/Proactor.h
@@ -66,8 +66,13 @@ public:
ACE_Handler *handler);
// This method is called when the timer is canceled
+ int deletion (TIMER_QUEUE &timer_queue,
+ ACE_Handler *handler,
+ const void *arg);
+ // This method is called when the timer queue is destroyed and
+ // the timer is still contained in it
+
protected:
-
int proactor (ACE_Proactor &proactor);
// Set the proactor. This will fail, if one is already set!
diff --git a/ace/Timer_Hash.h b/ace/Timer_Hash.h
new file mode 100644
index 00000000000..d3f465373d4
--- /dev/null
+++ b/ace/Timer_Hash.h
@@ -0,0 +1,64 @@
+/* -*- C++ -*- */
+
+// ============================================================================
+//
+// = LIBRARY
+// ace
+//
+// = FILENAME
+// Timer_Hash.h
+//
+// = AUTHOR
+// Darrell Brunsch <brunsch@cs.wustl.edu>
+//
+// ============================================================================
+
+#if !defined (ACE_TIMER_HASH_H)
+#define ACE_TIMER_HASH_H
+
+#include "ace/Timer_Hash_T.h"
+#include "ace/Timer_List_T.h"
+// The following typedef are here for ease of use
+
+typedef ACE_Timer_Hash_Upcall <ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX>
+ ACE_Hash_Upcall;
+
+typedef ACE_Timer_List_T <ACE_Event_Handler *,
+ ACE_Hash_Upcall,
+ ACE_Null_Mutex>
+ ACE_Hash_Timer_List;
+
+typedef ACE_Timer_Heap_T <ACE_Event_Handler *,
+ ACE_Hash_Upcall,
+ ACE_Null_Mutex>
+ ACE_Hash_Timer_Heap;
+
+
+typedef ACE_Timer_Hash_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX,
+ ACE_Hash_Timer_List>
+
+ ACE_Timer_Hash;
+
+typedef ACE_Timer_Hash_Iterator_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX,
+ ACE_Hash_Timer_List>
+ ACE_Timer_Hash_Iterator;
+
+typedef ACE_Timer_Hash_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX,
+ ACE_Hash_Timer_Heap>
+ ACE_Timer_Hash_Heap;
+
+typedef ACE_Timer_Hash_Iterator_T<ACE_Event_Handler *,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
+ ACE_SYNCH_RECURSIVE_MUTEX,
+ ACE_Hash_Timer_Heap>
+ ACE_Timer_Hash_Heap_Iterator;
+
+#endif /* ACE_TIMER_HASH_H */
diff --git a/ace/Timer_Hash_T.cpp b/ace/Timer_Hash_T.cpp
new file mode 100644
index 00000000000..e7389bb3675
--- /dev/null
+++ b/ace/Timer_Hash_T.cpp
@@ -0,0 +1,482 @@
+#if !defined (ACE_TIMER_HASH_T_C)
+#define ACE_TIMER_HASH_T_C
+
+#define ACE_BUILD_DLL
+
+#include "ace/Timer_Hash_T.h"
+
+struct Hash_Token
+{
+ Hash_Token (const void *act, size_t pos, long orig_id)
+ : act_ (act), pos_ (pos), orig_id_ (orig_id)
+ {}
+
+ const void *act_;
+ size_t pos_;
+ long orig_id_;
+};
+
+// Default constructor
+
+template <class TYPE, class FUNCTOR, class LOCK>
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>::ACE_Timer_Hash_Upcall (void)
+ : timer_hash_ (NULL)
+{
+ // Nothing
+}
+
+// Constructor that specifies a Timer_Hash to call up to
+
+template <class TYPE, class FUNCTOR, class LOCK>
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>::ACE_Timer_Hash_Upcall (ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK> *timer_hash)
+ : timer_hash_ (timer_hash)
+{
+ // Nothing
+}
+
+
+// Calls up to timer_hash's upcall functor
+
+template <class TYPE, class FUNCTOR, class LOCK> int
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>::timeout (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &cur_time)
+{
+ ACE_UNUSED_ARG (timer_queue);
+
+ Hash_Token *h = (Hash_Token *)arg;
+
+ int ret = this->timer_hash_->upcall_functor ().timeout (*this->timer_hash_,
+ handler,
+ h->act_,
+ cur_time);
+ delete h;
+ return ret;
+}
+
+
+// Calls up to timer_hash's upcall functor
+
+template <class TYPE, class FUNCTOR, class LOCK> int
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>::cancellation (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler)
+{
+ ACE_UNUSED_ARG (timer_queue);
+ return this->timer_hash_->upcall_functor ().cancellation (*this->timer_hash_,
+ handler);
+}
+
+
+// Calls up to timer_hash's upcall functor
+
+template <class TYPE, class FUNCTOR, class LOCK> int
+ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>::deletion (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg)
+{
+ ACE_UNUSED_ARG (timer_queue);
+
+ Hash_Token *h = (Hash_Token *)arg;
+
+ int ret = this->timer_hash_->upcall_functor ().deletion (*this->timer_hash_,
+ handler,
+ h->act_);
+ delete h;
+ return ret;
+}
+
+
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET>
+ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET>::ACE_Timer_Hash_Iterator_T (ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET> &hash)
+ : timer_hash_ (hash)
+{
+ // Nothing
+}
+
+
+// Positions the iterator at the first node in the timing hash table
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> void
+ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET>::first (void)
+{
+ for (this->position_ = 0;
+ this->position_ < this->timer_hash_.table_size_;
+ this->position_++)
+ {
+ // Check for an empty entry
+ if (!this->timer_hash_.table_[this->position_]->is_empty ())
+ {
+ this->iter_ = &this->timer_hash_.table_[this->position_]->iter ();
+ this->iter_->first ();
+ return;
+ }
+ }
+
+ // Didn't find any
+ this->iter_ = NULL;
+}
+
+
+// Positions the iterator at the next node in the bucket or goes to the next
+// bucket
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> void
+ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET>::next (void)
+{
+ if (this->isdone ())
+ return;
+
+ // If there is no more in the current bucket, go to the next
+ if (this->iter_->isdone ())
+ {
+ for (this->position_++; this->position_ < this->timer_hash_.table_size_; this->position_++)
+ {
+ // Check for an empty entry
+ if (!this->timer_hash_.table_[this->position_]->is_empty ())
+ {
+ this->iter_ = &this->timer_hash_.table_[this->position_]->iter ();
+ this->iter_->first ();
+ return;
+ }
+ }
+
+ // Didn't find any
+ this->iter_ = NULL;
+ }
+ else
+ this->iter_->next ();
+}
+
+
+// Returns true when we are at the end (when bucket_item_ == 0)
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> int
+ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET>::isdone (void)
+{
+ return this->iter_ == NULL;
+}
+
+
+// Returns the node at the current position in the sequence
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET>::item (void)
+{
+ if (this->isdone ())
+ return NULL;
+
+ return this->iter_->item ();
+}
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK> &
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::iter (void)
+{
+ return this->iterator_;
+}
+
+// Create an empty queue.
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET>
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::ACE_Timer_Hash_T (size_t table_size,
+ FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
+ : ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK> (upcall_functor, freelist),
+ size_ (0),
+ table_ (new BUCKET* [table_size]),
+ table_size_ (table_size),
+ table_functor_ (this),
+ earliest_position_ (0),
+ iterator_ (*this)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::ACE_Timer_Hash_T");
+
+ this->gettimeofday (ACE_High_Res_Timer::gettimeofday);
+
+ for (size_t i = 0; i < table_size; i++)
+ {
+ this->table_[i] = new BUCKET;
+ this->table_[i]->gettimeofday (ACE_High_Res_Timer::gettimeofday);
+ this->table_[i]->set_upcall_functor (&this->table_functor_);
+ this->table_[i]->free_list (this->free_list_);
+ }
+
+ this->table_functor_;
+}
+
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET>
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::ACE_Timer_Hash_T (FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
+ : ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK> (upcall_functor, freelist),
+ size_ (0),
+ table_ (new BUCKET* [ACE_DEFAULT_TIMER_HASH_TABLE_SIZE]),
+ table_size_ (ACE_DEFAULT_TIMER_HASH_TABLE_SIZE),
+ table_functor_ (this),
+ earliest_position_ (0),
+ iterator_ (*this)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::ACE_Timer_Hash_T");
+
+ this->gettimeofday (ACE_High_Res_Timer::gettimeofday);
+
+ for (size_t i = 0; i < this->table_size_; i++)
+ {
+ this->table_[i] = new BUCKET (&this->table_functor_, this->free_list_);
+ this->table_[i]->gettimeofday (ACE_High_Res_Timer::gettimeofday);
+ }
+
+ this->table_functor_;
+}
+
+
+// Remove all remaining items in the Queue.
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET>
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::~ACE_Timer_Hash_T (void)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::~ACE_Timer_Hash_T");
+ ACE_MT (ACE_GUARD (LOCK, ace_mon, this->mutex_));
+
+ for (size_t i = 0; i < this->table_size_; i++)
+ delete this->table_[i];
+
+ delete [] this->table_;
+}
+
+// Checks if queue is empty.
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> int
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::is_empty (void) const
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::is_empty");
+ return this->table_[this->earliest_position_]->is_empty ();
+}
+
+
+// Returns earliest time in a non-empty bucket
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> const ACE_Time_Value &
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::earliest_time (void) const
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::earliest_time");
+ return this->table_[this->earliest_position_]->earliest_time ();
+}
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> void
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::dump (void) const
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::dump");
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, "\ntable_size_ = %d", this->table_size_));
+ ACE_DEBUG ((LM_DEBUG, "\nearliest_position_ = %d", this->earliest_position_));
+ for (size_t i = 0; i < this->table_size_; i++)
+ if (!this->table_[i]->is_empty ())
+ ACE_DEBUG ((LM_DEBUG, "\nBucket %d contains nodes", i));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+}
+
+
+// Reschedule a periodic timer. This function must be called with the
+// mutex lock held.
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> void
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::reschedule (ACE_Timer_Node_T<TYPE> *expired)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::reschedule");
+
+ size_t position = expired->get_timer_value ().usec () % this->table_size_;
+
+ Hash_Token *h = (Hash_Token *)expired->get_act ();
+
+ h->orig_id_ = this->table_[position]->schedule (expired->get_type (),
+ h,
+ expired->get_timer_value (),
+ expired->get_interval ());
+
+ if (this->table_[this->earliest_position_]->is_empty ()
+ || this->table_[this->earliest_position_]->earliest_time () < this->table_[position]->earliest_time ())
+ this->earliest_position_ = position;
+}
+
+
+// Insert a new handler that expires at time future_time; if interval
+// is > 0, the handler will be reinvoked periodically.
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> long
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::schedule (const TYPE &type,
+ const void *act,
+ const ACE_Time_Value &future_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::schedule");
+ ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, this->mutex_, -1));
+
+ size_t position = future_time.usec () % this->table_size_;
+
+ Hash_Token *h = new Hash_Token (act, position, 0);
+
+ h->orig_id_ = this->table_[position]->schedule (type,
+ h,
+ future_time,
+ interval);
+
+ if (this->table_[this->earliest_position_]->is_empty ()
+ || this->table_[this->earliest_position_]->earliest_time () < this->table_[position]->earliest_time ())
+ this->earliest_position_ = position;
+
+ ++this->size_;
+
+ return (long) h;
+}
+
+// Locate and remove the single <ACE_Event_Handler> with a value of
+// <timer_id> from the correct table timer queue.
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> int
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::cancel (long timer_id,
+ const void **act,
+ int dont_call)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::cancel");
+ ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, this->mutex_, -1));
+
+ // Make sure we are getting a valid <timer_id>, not an error
+ // returned by schedule ()
+ if (timer_id == -1)
+ return 0;
+
+ Hash_Token *h = (Hash_Token *)timer_id;
+
+ int ret = this->table_[h->pos_]->cancel (h->orig_id_, act, dont_call);
+
+ if (act != 0)
+ *act = h->act_;
+
+ delete h;
+
+ --this->size_;
+
+ return ret;
+}
+
+
+// Locate and remove all values of <type> from the timer queue.
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> int
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::cancel (const TYPE &type,
+ int dont_call)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::cancel");
+ ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, this->mutex_, -1));
+
+ size_t i; // loop variable
+
+ Hash_Token **timer_ids = new Hash_Token *[this->size_];
+ size_t pos = 0;
+
+ for (i = 0; i < this->table_size_; i++)
+ {
+ ACE_Timer_Queue_Iterator_T<TYPE, ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>, ACE_Null_Mutex> &iter = this->table_[i]->iter ();
+ for (iter.first (); !iter.isdone (); iter.next ())
+ timer_ids[pos++] = (Hash_Token *)iter.item ()->get_act ();
+ }
+
+ ACE_ASSERT (pos <= this->size_);
+
+ for (i = 0; i < pos; i++)
+ {
+ this->table_[timer_ids[i]->pos_]->cancel (timer_ids[i]->orig_id_, 0, dont_call);
+
+ dont_call = 1; // Make sure the functor is only called on the first expiration
+
+ delete timer_ids[i];
+
+ --this->size_;
+ }
+
+ delete timer_ids;
+
+ return pos;
+}
+
+
+// Removes the earliest node and finds the new earliest position
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::remove_first (void)
+{
+ if (this->is_empty ())
+ return NULL;
+
+ ACE_Timer_Node_T<TYPE> *temp = this->table_[this->earliest_position_]->remove_first ();
+
+ for (size_t i = 0; i < this->table_size_; i++)
+ if (!this->table_[i]->is_empty ())
+ if (this->earliest_time () == ACE_Time_Value::zero
+ || this->table_[i]->earliest_time () < this->earliest_time ())
+ this->earliest_position_ = i;
+
+ --this->size_;
+
+ return temp;
+}
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET> int
+ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET>::expire (const ACE_Time_Value &cur_time)
+{
+ ACE_TRACE ("ACE_Timer_Hash_T::expire");
+ ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, this->mutex_, -1));
+
+ int number_of_timers_expired = 0;
+
+ ACE_Timer_Node_T<TYPE> *expired;
+
+ // Go through the table and expire anything that can be expired
+
+ for (size_t i = 0; i < this->table_size_; i++)
+ {
+ while (!this->table_[i]->is_empty () &&
+ this->table_[i]->earliest_time () <= cur_time)
+ {
+ expired = this->table_[i]->remove_first ();
+ --this->size_;
+ TYPE &type = expired->get_type ();
+ const void *act = expired->get_act ();
+ int reclaim = 1;
+
+ // 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);
+ reclaim = 0;
+ }
+
+ // call the functor
+ Hash_Token *h = (Hash_Token *)act;
+ this->upcall (type, h->act_, cur_time);
+
+ if (reclaim)
+ {
+ // Free up the node and the token
+ this->free_node (expired);
+ delete h;
+ }
+
+ number_of_timers_expired++;
+ }
+ }
+
+ return number_of_timers_expired;
+}
+
+#endif /* ACE_TIMER_HASH_T_C */
diff --git a/ace/Timer_Hash_T.h b/ace/Timer_Hash_T.h
new file mode 100644
index 00000000000..d6f61084c2b
--- /dev/null
+++ b/ace/Timer_Hash_T.h
@@ -0,0 +1,234 @@
+/* -*- C++ -*- */
+
+// ============================================================================
+//
+// = LIBRARY
+// ace
+//
+// = FILENAME
+// Timer_Hash_T.h
+//
+// = AUTHOR
+// Darrell Brunsch <brunsch@cs.wustl.edu>
+//
+// ============================================================================
+
+#if !defined (ACE_TIMER_HASH_T_H)
+#define ACE_TIMER_HASH_T_H
+
+#include "ace/Timer_Queue.h"
+#include "ace/Free_List.h"
+
+// Forward declaration.
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET>
+class ACE_Timer_Hash_T;
+
+template <class TYPE, class FUNCTOR, class LOCK>
+class ACE_Timer_Hash_Upcall
+ // = TITLE
+ // Functor for Timer_Hash
+ //
+ // = DESCRIPTION
+ // This class calls up to the Timer Hash's functor from the
+ // timer queues in the hash table
+{
+public:
+ typedef ACE_Timer_Queue_T<ACE_Event_Handler *,
+ ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>,
+ ACE_Null_Mutex>
+ TIMER_QUEUE;
+
+ ACE_Timer_Hash_Upcall (void);
+ // Default constructor (creates an invalid object, but needs to be here
+ // so timer queues using this functor can be constructed)
+
+ ACE_Timer_Hash_Upcall (ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK> *timer_hash);
+ // Constructor that specifies a Timer_Hash to call up to
+
+ int timeout (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg,
+ const ACE_Time_Value &cur_time);
+ // This method is called when the timer expires
+
+ int cancellation (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler);
+ // This method is called when the timer is canceled
+
+ int deletion (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg);
+ // This method is called when the timer queue is destroyed and
+ // the timer is still contained in it
+
+private:
+ ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK> *timer_hash_;
+ // Timer Queue to do the calling up to
+
+ // = Don't allow these operations for now.
+ ACE_Timer_Hash_Upcall (const ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK> &);
+ void operator= (const ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK> &);
+};
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET>
+class ACE_Timer_Hash_Iterator_T : public ACE_Timer_Queue_Iterator_T <TYPE, FUNCTOR, LOCK>
+ // = TITLE
+ // Iterates over an <ACE_Timer_Hash>.
+ //
+ // = DESCRIPTION
+ // This is a generic iterator that can be used to visit every
+ // node of a timer queue. Be aware that it doesn't transverse
+ // in the order of timeout values.
+{
+public:
+ ACE_Timer_Hash_Iterator_T (ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET> &);
+ // Constructor.
+
+ virtual void first (void);
+ // Positions the iterator at the earliest node in the Timer Queue
+
+ virtual void next (void);
+ // Positions the iterator at the next node in the Timer Queue
+
+ virtual int isdone (void);
+ // Returns true when there are no more nodes in the sequence
+
+ virtual ACE_Timer_Node_T<TYPE> *item (void);
+ // Returns the node at the current position in the sequence
+
+protected:
+ ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET> &timer_hash_;
+ // Pointer to the <ACE_Timer_Hash> that we are iterating over.
+
+ size_t position_;
+ // Current position in <timer_hash_>'s table
+
+ ACE_Timer_Queue_Iterator_T<TYPE, ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK>, ACE_Null_Mutex> *iter_;
+ // Current iterator used on <position>'s bucket
+};
+
+template <class TYPE, class FUNCTOR, class LOCK, class BUCKET>
+class ACE_Timer_Hash_T : public ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>
+ // = TITLE
+ // Provides a hash table of <BUCKET>s as an implementation for
+ // a timer queue.
+ //
+ // = DESCRIPTION
+ // This implementation uses a hash table of BUCKETs. The hash
+ // is based on the time_value of the event. Unlike other Timer
+ // Queues, ACE_Timer_Hash does not expire events in order.
+{
+public:
+ typedef ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET> HASH_ITERATOR;
+ // Type of iterator
+
+ friend class ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, LOCK, BUCKET>;
+ // Iterator is a friend
+
+ typedef ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK> INHERITED;
+ // Type inherited from
+
+ // = Initialization and termination methods.
+ ACE_Timer_Hash_T (size_t table_size,
+ FUNCTOR *upcall_functor = 0,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
+ // Default constructor. <table_size> determines the size of the
+ // hash table. <upcall_functor> is the instance of the FUNCTOR
+ // to be used by the buckets. If <upcall_functor> is 0, a default
+ // FUNCTOR will be created.
+
+ ACE_Timer_Hash_T (FUNCTOR *upcall_functor = 0, ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
+ // Default constructor. <upcall_functor> is the instance of the
+ // FUNCTOR to be used by the queue. If <upcall_functor> is 0, Timer
+ // Hash will create a default FUNCTOR. <freelist> the freelist of
+ // timer nodes. If 0, then a default freelist will be created. The default
+ // size will be ACE_DEFAULT_TIMERS and there will be no preallocation.
+
+ virtual ~ACE_Timer_Hash_T (void);
+ // Destructor
+
+ virtual int is_empty (void) const;
+ // True if queue is empty, else false.
+
+ virtual const ACE_Time_Value &earliest_time (void) const;
+ // Returns the time of the earlier node in the <ACE_Timer_Hash>.
+
+ virtual long schedule (const TYPE &type,
+ const void *act,
+ const ACE_Time_Value &delay,
+ const ACE_Time_Value &interval = ACE_Time_Value::zero);
+ // Schedule <type> that will expire after <delay> amount of time.
+ // If it expires then <act> is passed in as the value to the
+ // <functor>. If <interval> is != to <ACE_Time_Value::zero> then it
+ // is used to reschedule the <type> automatically. This method
+ // returns a <timer_id> that is a pointer to a token which stores
+ // information about the event. This <timer_id> can be used to cancel
+ // the timer before it expires. Returns -1 on failure.
+
+ virtual int cancel (const TYPE &type,
+ int dont_call_handle_close = 1);
+ // Cancel all timer associated with <type>. If <dont_call> is 0
+ // then the <functor> will be invoked. Returns number of timers
+ // cancelled.
+
+ virtual int cancel (long timer_id,
+ const void **act = 0,
+ int dont_call_handle_close = 1);
+ // Cancel the single timer that matches the <timer_id> value (which
+ // was returned from the <schedule> method). If act is non-NULL
+ // then it will be set to point to the ``magic cookie'' argument
+ // passed in when the timer was registered. This makes it possible
+ // to free up the memory and avoid memory leaks. If <dont_call> is
+ // 0 then the <functor> will be invoked. Returns 1 if cancellation
+ // succeeded and 0 if the <timer_id> wasn't found.
+
+ virtual int expire (const ACE_Time_Value &current_time);
+ // Run the <functor> for all timers whose values are <= <cur_time>.
+ // This does not account for <timer_skew>. Returns the number of
+ // timers canceled.
+
+ virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK> &iter (void);
+ // Returns a pointer to this <ACE_Timer_Queue>'s iterator.
+
+ virtual ACE_Timer_Node_T<TYPE> *remove_first (void);
+ // Removes the earliest node from the queue and returns it
+
+ virtual void dump (void) const;
+ // Dump the state of an object.
+
+private:
+ virtual void reschedule (ACE_Timer_Node_T<TYPE> *);
+ // Reschedule an "interval" <ACE_Timer_Node>.
+
+ size_t size_;
+ // Keeps track of the size of the queue
+
+ BUCKET **table_;
+ // Table of BUCKETS
+
+ size_t table_size_;
+ // Keeps track of the size of <table>
+
+ ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, LOCK> table_functor_;
+ // Functor used for the table's timer queues
+
+ size_t earliest_position_;
+ // Index to the position with the earliest entry
+
+ HASH_ITERATOR iterator_;
+ // Iterator used to expire timers.
+
+ // = Don't allow these operations for now.
+ ACE_Timer_Hash_T (const ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET> &);
+ void operator= (const ACE_Timer_Hash_T<TYPE, FUNCTOR, LOCK, BUCKET> &);
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Timer_Hash_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Timer_Hash_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* ACE_TIMER_HASH_T_H */
diff --git a/ace/Timer_Heap.h b/ace/Timer_Heap.h
index 676ed3b352d..46132a49ef8 100644
--- a/ace/Timer_Heap.h
+++ b/ace/Timer_Heap.h
@@ -23,12 +23,12 @@
// compatibility.
typedef ACE_Timer_Heap_T<ACE_Event_Handler *,
- ACE_Event_Handler_Handle_Timeout_Upcall,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
ACE_SYNCH_RECURSIVE_MUTEX>
ACE_Timer_Heap;
typedef ACE_Timer_Heap_Iterator_T<ACE_Event_Handler *,
- ACE_Event_Handler_Handle_Timeout_Upcall,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
ACE_SYNCH_RECURSIVE_MUTEX>
ACE_Timer_Heap_Iterator;
diff --git a/ace/Timer_Heap_T.cpp b/ace/Timer_Heap_T.cpp
index 3983b8460c7..54c77eac3e3 100644
--- a/ace/Timer_Heap_T.cpp
+++ b/ace/Timer_Heap_T.cpp
@@ -1,5 +1,3 @@
-// $Id$
-
#if !defined (ACE_TIMER_HEAP_T_C)
#define ACE_TIMER_HEAP_T_C
@@ -11,6 +9,9 @@
#define ACE_HEAP_PARENT(X) (X == 0 ? 0 : (((X) - 1) / 2))
#define ACE_HEAP_LCHILD(X) (((X)+(X))+1)
+
+// Constructor that takes in an <ACE_Timer_Heap_T> to iterate over.
+
template <class TYPE, class FUNCTOR, class LOCK>
ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Heap_Iterator_T (ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK> &heap)
: timer_heap_ (heap)
@@ -19,29 +20,52 @@ ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Heap_Iterator_T (ACE_T
}
-template <class TYPE, class FUNCTOR, class LOCK> int
-ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, LOCK>::next (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *&node,
- const ACE_Time_Value &cur_time)
+// Positions the iterator at the first node in the heap array
+
+template <class TYPE, class FUNCTOR, class LOCK> void
+ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, LOCK>::first (void)
{
- ACE_TRACE ("ACE_Timer_Heap_Iterator::next");
+ this->position_ = 0;
+}
- if (this->timer_heap_.cur_size_ == 0
- || this->timer_heap_.heap_[0]->timer_value_ > cur_time)
- return 0;
- else
- {
- // Remove the first item and restore the heap property.
- node = this->timer_heap_.remove (0);
- return 1;
- }
+// Positions the iterator at the next node in the heap array
+
+template <class TYPE, class FUNCTOR, class LOCK> void
+ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, LOCK>::next (void)
+{
+ if (this->position_ != this->timer_heap_.cur_size_)
+ this->position_++;
}
+
+// Returns true the <position_> is at the end of the heap array
+
+template <class TYPE, class FUNCTOR, class LOCK> int
+ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, LOCK>::isdone (void)
+{
+ return this->position_ == this->timer_heap_.cur_size_;
+}
+
+
+// Returns the node at the current position in the heap or NULL if at the end
+
+template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, LOCK>::item (void)
+{
+ if (this->position_ != this->timer_heap_.cur_size_)
+ return this->timer_heap_.heap_[this->position_];
+ return NULL;
+}
+
+// Constructor
+
template <class TYPE, class FUNCTOR, class LOCK>
ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Heap_T (size_t size,
int preallocate,
- FUNCTOR *upcall_functor)
- : INHERITED (upcall_functor),
+ FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
+ : INHERITED (upcall_functor, freelist),
max_size_ (size),
cur_size_ (0),
iterator_ (*this),
@@ -49,10 +73,10 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Heap_T (size_t size,
preallocated_nodes_ (0),
preallocated_nodes_freelist_ (0)
{
- ACE_TRACE ("ACE_Timer_Heap::ACE_Timer_Heap");
+ ACE_TRACE ("ACE_Timer_Heap_T::ACE_Timer_Heap_T");
// Create the heap array.
- ACE_NEW (this->heap_, (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *[size]));
+ ACE_NEW (this->heap_, (ACE_Timer_Node_T<TYPE> *[size]));
// Create the parallel
ACE_NEW (this->timer_ids_, long[size]);
@@ -66,7 +90,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Heap_T (size_t size,
if (preallocate)
{
ACE_NEW (this->preallocated_nodes_,
- (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>[size]));
+ (ACE_Timer_Node_T<TYPE>[size]));
// Add allocated array to set of such arrays for deletion
// on cleanup.
@@ -74,11 +98,10 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Heap_T (size_t size,
// Form the freelist by linking the next_ pointers together.
for (size_t j = 1; j < size; j++)
- this->preallocated_nodes_[j - 1].next_ =
- &this->preallocated_nodes_[j];
+ this->preallocated_nodes_[j - 1].set_next (&this->preallocated_nodes_[j]);
// NULL-terminate the freelist.
- this->preallocated_nodes_[size - 1].next_ = 0;
+ this->preallocated_nodes_[size - 1].set_next (0);
// Assign the freelist pointer to the front of the list.
this->preallocated_nodes_freelist_ =
@@ -87,19 +110,57 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Heap_T (size_t size,
}
template <class TYPE, class FUNCTOR, class LOCK>
+ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Heap_T (FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
+ : INHERITED (upcall_functor, freelist),
+ max_size_ (ACE_DEFAULT_TIMERS),
+ cur_size_ (0),
+ iterator_ (*this),
+ timer_ids_freelist_ (0),
+ preallocated_nodes_ (0),
+ preallocated_nodes_freelist_ (0)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::ACE_Timer_Heap_T");
+
+ // Create the heap array.
+ ACE_NEW (this->heap_, (ACE_Timer_Node_T<TYPE> *[this->max_size_]));
+
+ // Create the parallel
+ ACE_NEW (this->timer_ids_, long[this->max_size_]);
+
+ // Initialize the "freelist," which uses negative values to
+ // distinguish freelist elements from "pointers" into the <heap_>
+ // array.
+ for (size_t i = 0; i < this->max_size_; i++)
+ this->timer_ids_[i] = -((long) (i + 1));
+}
+
+
+template <class TYPE, class FUNCTOR, class LOCK>
ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::~ACE_Timer_Heap_T (void)
{
ACE_TRACE ("ACE_Timer_Heap::~ACE_Timer_Heap");
+
+ // Clean up all the nodes still in the queue
+ for (size_t i = 0; i < this->cur_size_; )
+ {
+ this->upcall_functor ().deletion (*this,
+ this->heap_[i]->get_type (),
+ this->heap_[i]->get_act ());
+ this->free_node (this->heap_[i]);
+ }
+
+
delete [] this->heap_;
delete [] this->timer_ids_;
// clean up any preallocated timer nodes
if (preallocated_nodes_ != 0)
{
- ACE_Unbounded_Set_Iterator<ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *>
+ ACE_Unbounded_Set_Iterator<ACE_Timer_Node_T<TYPE> *>
set_iterator (this->preallocated_node_set_);
- for (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> **entry = 0;
+ for (ACE_Timer_Node_T<TYPE> **entry = 0;
set_iterator.next (entry) !=0;
set_iterator.advance ())
delete [] *entry;
@@ -107,6 +168,8 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::~ACE_Timer_Heap_T (void)
}
+
+
template <class TYPE, class FUNCTOR, class LOCK> int
ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::pop_freelist (void)
{
@@ -164,7 +227,7 @@ template <class TYPE, class FUNCTOR, class LOCK> const ACE_Time_Value &
ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::earliest_time (void) const
{
ACE_TRACE ("ACE_Timer_Heap::earliest_time");
- return this->heap_[0]->timer_value_;
+ return this->heap_[0]->get_timer_value ();
}
@@ -193,24 +256,24 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::dump (void) const
}
template <class TYPE, class FUNCTOR, class LOCK> void
-ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::copy (int index, ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *moved_node)
+ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::copy (int index, ACE_Timer_Node_T<TYPE> *moved_node)
{
// Insert <moved_node> into its new location in the heap.
this->heap_[index] = moved_node;
- ACE_ASSERT (moved_node->timer_id_ >= 0
- && moved_node->timer_id_ < (int) this->max_size_);
+ ACE_ASSERT (moved_node->get_timer_id () >= 0
+ && moved_node->get_timer_id () < (int) this->max_size_);
// Update the corresponding slot in the parallel <timer_ids_> array.
- this->timer_ids_[moved_node->timer_id_] = index;
+ this->timer_ids_[moved_node->get_timer_id ()] = index;
}
-template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *
+template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T<TYPE> *
ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::remove (size_t index)
{
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *removed_node = this->heap_[index];
+ ACE_Timer_Node_T<TYPE> *removed_node = this->heap_[index];
// Return this timer id to the freelist.
- this->push_freelist (removed_node->timer_id_);
+ this->push_freelist (removed_node->get_timer_id ());
// Decrement the size of the heap by one since we're removing the
// "index"th node.
@@ -220,7 +283,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::remove (size_t index)
if (index < this->cur_size_)
{
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *moved_node = this->heap_[this->cur_size_];
+ ACE_Timer_Node_T<TYPE> *moved_node = this->heap_[this->cur_size_];
// Move the end node to the location being removed and update
// the corresponding slot in the parallel <timer_ids> array.
@@ -230,7 +293,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::remove (size_t index)
// parent it needs be moved down the heap.
size_t parent = ACE_HEAP_PARENT (index);
- if (moved_node->timer_value_ >= this->heap_[parent]->timer_value_)
+ if (moved_node->get_timer_value () >= this->heap_[parent]->get_timer_value ())
this->reheap_down (moved_node, index, ACE_HEAP_LCHILD (index));
else
this->reheap_up (moved_node, index, parent);
@@ -240,7 +303,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::remove (size_t index)
}
template <class TYPE, class FUNCTOR, class LOCK> void
-ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::reheap_down (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *moved_node,
+ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::reheap_down (ACE_Timer_Node_T<TYPE> *moved_node,
size_t index,
size_t child)
{
@@ -250,12 +313,12 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::reheap_down (ACE_Timer_Node_T<TYPE, FUNCT
{
// Choose the smaller of the two children.
if (child + 1 < this->cur_size_
- && this->heap_[child + 1]->timer_value_ < this->heap_[child]->timer_value_)
+ && this->heap_[child + 1]->get_timer_value () < this->heap_[child]->get_timer_value ())
child++;
// Perform a <copy> if the child has a larger timeout value than
// the <moved_node>.
- if (this->heap_[child]->timer_value_ < moved_node->timer_value_)
+ if (this->heap_[child]->get_timer_value () < moved_node->get_timer_value ())
{
this->copy (index, this->heap_[child]);
index = child;
@@ -270,7 +333,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::reheap_down (ACE_Timer_Node_T<TYPE, FUNCT
}
template <class TYPE, class FUNCTOR, class LOCK> void
-ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::reheap_up (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *moved_node,
+ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::reheap_up (ACE_Timer_Node_T<TYPE> *moved_node,
size_t index,
size_t parent)
{
@@ -280,7 +343,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::reheap_up (ACE_Timer_Node_T<TYPE, FUNCTOR
{
// If the parent node is greater than the <moved_node> we need
// to copy it down.
- if (moved_node->timer_value_ < this->heap_[parent]->timer_value_)
+ if (moved_node->get_timer_value () < this->heap_[parent]->get_timer_value ())
{
this->copy (index, this->heap_[parent]);
index = parent;
@@ -296,7 +359,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::reheap_up (ACE_Timer_Node_T<TYPE, FUNCTOR
}
template <class TYPE, class FUNCTOR, class LOCK> void
-ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::insert (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *new_node)
+ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::insert (ACE_Timer_Node_T<TYPE> *new_node)
{
if (this->cur_size_ + 1 >= max_size_)
this->grow_heap ();
@@ -316,8 +379,8 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::grow_heap (void)
// First grow the heap itself.
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> **new_heap = 0;
- ACE_NEW (new_heap, (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *[new_size]));
+ ACE_Timer_Node_T<TYPE> **new_heap = 0;
+ ACE_NEW (new_heap, (ACE_Timer_Node_T<TYPE> *[new_size]));
ACE_OS::memcpy (new_heap, this->heap_,
max_size_ * sizeof *new_heap);
delete [] this->heap_;
@@ -346,32 +409,31 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::grow_heap (void)
// Create a new array with max_size elements to link in
// to existing list.
ACE_NEW (this->preallocated_nodes_,
- (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>[this->max_size_]));
+ (ACE_Timer_Node_T<TYPE>[this->max_size_]));
// Add it to the set for later deletion
this->preallocated_node_set_.insert (this->preallocated_nodes_);
// link new nodes together (as for original list).
for (size_t k = 1; k < this->max_size_; k++)
- this->preallocated_nodes_[k - 1].next_ =
- &this->preallocated_nodes_[k];
+ this->preallocated_nodes_[k - 1].set_next (&this->preallocated_nodes_[k]);
// NULL-terminate the new list.
- this->preallocated_nodes_[this->max_size_ - 1].next_ = 0;
+ this->preallocated_nodes_[this->max_size_ - 1].set_next (0);
// link new array to the end of the existling list
if (this->preallocated_nodes_freelist_ == 0)
this->preallocated_nodes_freelist_ = &preallocated_nodes_[0];
else
{
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *previous = this->preallocated_nodes_freelist_;
+ ACE_Timer_Node_T<TYPE> *previous = this->preallocated_nodes_freelist_;
- for (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *current = this->preallocated_nodes_freelist_->next_;
+ for (ACE_Timer_Node_T<TYPE> *current = this->preallocated_nodes_freelist_->get_next ();
current != 0;
- current = current->next_)
+ current = current->get_next ())
previous = current;
- previous->next_ = &this->preallocated_nodes_[0];
+ previous->set_next (&this->preallocated_nodes_[0]);
}
}
@@ -382,7 +444,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::grow_heap (void)
// mutex lock held.
template <class TYPE, class FUNCTOR, class LOCK> void
-ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::reschedule (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *expired)
+ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::reschedule (ACE_Timer_Node_T<TYPE> *expired)
{
ACE_TRACE ("ACE_Timer_Heap::reschedule");
@@ -391,7 +453,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::reschedule (ACE_Timer_Node_T<TYPE, FUNCTO
}
-template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *
+template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T<TYPE> *
ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::alloc_node (void)
{
ACE_Timer_Node *temp;
@@ -399,7 +461,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::alloc_node (void)
// Only allocate a node if we are *not* using the preallocated heap.
if (this->preallocated_nodes_ == 0)
ACE_NEW_RETURN (temp,
- (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>),
+ (ACE_Timer_Node_T<TYPE>),
0);
else
{
@@ -411,21 +473,21 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::alloc_node (void)
// Remove the first element from the freelist.
this->preallocated_nodes_freelist_ =
- this->preallocated_nodes_freelist_->next_;
+ this->preallocated_nodes_freelist_->get_next ();
}
return temp;
}
template <class TYPE, class FUNCTOR, class LOCK> void
-ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::free_node (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *node)
+ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::free_node (ACE_Timer_Node_T<TYPE> *node)
{
// Only free up a node if we are *not* using the preallocated heap.
if (this->preallocated_nodes_ == 0)
delete node;
else
{
- node->next_ = this->preallocated_nodes_freelist_;
+ node->set_next (this->preallocated_nodes_freelist_);
this->preallocated_nodes_freelist_ = node;
}
}
@@ -450,17 +512,17 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::schedule (const TYPE &type,
int timer_id = this->timer_id ();
// Obtain the memory to the new node.
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *temp = this->alloc_node ();
+ ACE_Timer_Node_T<TYPE> *temp = this->alloc_node ();
if (temp)
{
- // Use operator placement new.
- new (temp) ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> (type,
- act,
- future_time,
- interval,
- 0,
- timer_id);
+ temp->set (type,
+ act,
+ future_time,
+ interval,
+ 0,
+ timer_id);
+
this->insert (temp);
return timer_id;
}
@@ -485,21 +547,21 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::cancel (long timer_id,
long timer_node_slot = this->timer_ids_[timer_id];
- if (timer_id != this->heap_[timer_node_slot]->timer_id_)
+ if (timer_id != this->heap_[timer_node_slot]->get_timer_id ())
{
- ACE_ASSERT (timer_id == this->heap_[timer_node_slot]->timer_id_);
+ ACE_ASSERT (timer_id == this->heap_[timer_node_slot]->get_timer_id ());
return 0;
}
else
{
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *temp = this->remove (timer_node_slot);
+ ACE_Timer_Node_T<TYPE> *temp = this->remove (timer_node_slot);
if (dont_call == 0)
// Call the close hook.
- this->upcall_functor_.cancellation (*this, temp->type_);
+ this->upcall_functor ().cancellation (*this, temp->get_type ());
if (act != 0)
- *act = temp->act_;
+ *act = temp->get_act ();
this->free_node (temp);
return 1;
@@ -521,16 +583,16 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::cancel (const TYPE &type,
for (size_t i = 0; i < this->cur_size_; )
{
- if (this->heap_[i]->type_ == type)
+ if (this->heap_[i]->get_type () == type)
{
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *temp = this->remove (i);
+ ACE_Timer_Node_T<TYPE> *temp = this->remove (i);
number_of_cancellations++;
if (dont_call == 0
&& number_of_cancellations == 1)
// Call the close hook.
- this->upcall_functor_.cancellation (*this, temp->type_);
+ this->upcall_functor ().cancellation (*this, temp->get_type ());
this->free_node (temp);
}
@@ -541,5 +603,19 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::cancel (const TYPE &type,
return number_of_cancellations;
}
+
+// Returns the earliest node or returns NULL if the heap is empty.
+
+template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T <TYPE> *
+ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>::remove_first (void)
+{
+ ACE_TRACE ("ACE_Timer_Heap_T::remove_first");
+
+ if (this->cur_size_ == 0)
+ return NULL;
+
+ return this->remove (0);
+}
+
#endif /* ACE_TIMER_HEAP_T_C */
diff --git a/ace/Timer_Heap_T.h b/ace/Timer_Heap_T.h
index 2a2780f2137..0d0e2c9d0cd 100644
--- a/ace/Timer_Heap_T.h
+++ b/ace/Timer_Heap_T.h
@@ -1,6 +1,4 @@
/* -*- C++ -*- */
-// $Id$
-
// ============================================================================
//
// = LIBRARY
@@ -18,6 +16,7 @@
#define ACE_TIMER_HEAP_T_H
#include "ace/Timer_Queue.h"
+#include "ace/Free_List.h"
#include "ace/Containers.h"
// Forward declaration
@@ -27,26 +26,35 @@ class ACE_Timer_Heap_T;
template <class TYPE, class FUNCTOR, class LOCK>
class ACE_Timer_Heap_Iterator_T : public ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK>
// = TITLE
- // Iterates over an <ACE_Timer_Queue>.
+ // Iterates over an <ACE_Timer_Hash_T>.
//
// = DESCRIPTION
- // This is a special type of iterator that "advances" by moving
- // the head of the timer queue up by one every time.
+ // This is a generic iterator that can be used to visit every
+ // node of a timer queue. Be aware that it doesn't transverse
+ // in the order of timeout values.
{
public:
ACE_Timer_Heap_Iterator_T (ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK> &);
// Constructor.
- virtual int next (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *&timer_node,
- const ACE_Time_Value &cur_time);
- // Pass back the next <timer_node> that hasn't been seen yet, if its
- // <time_value_> <= <cur_time>. In addition, moves the timer queue
- // forward by one node. Returns 0 when all <timer_nodes> have been
- // seen, else 1.
+ virtual void first (void);
+ // Positions the iterator at the earliest node in the Timer Queue
+
+ virtual void next (void);
+ // Positions the iterator at the next node in the Timer Queue
+
+ virtual int isdone (void);
+ // Returns true when there are no more nodes in the sequence
+
+ virtual ACE_Timer_Node_T<TYPE> *item (void);
+ // Returns the node at the current position in the sequence
protected:
ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK> &timer_heap_;
// Pointer to the <ACE_Timer_Heap> that we are iterating over.
+
+ size_t position_;
+ // Position in the array where the iterator is at
};
template <class TYPE, class FUNCTOR, class LOCK>
@@ -72,14 +80,23 @@ public:
typedef ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK> INHERITED;
// = Initialization and termination methods.
- ACE_Timer_Heap_T (size_t size = ACE_DEFAULT_TIMERS,
+ ACE_Timer_Heap_T (size_t size,
int preallocated = 0,
- FUNCTOR *upcall_functor = 0);
+ FUNCTOR *upcall_functor = 0,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
// The Constructor creates a heap with <size> elements. If
// <preallocated> is non-0 then we'll pre-allocate all the memory
// for the <ACE_Timer_Nodes>. This saves time and is more
// predictable (though it requires more space). Otherwise, we'll
- // just allocate the nodes as we need them.
+ // just allocate the nodes as we need them. This can also take in a
+ // upcall functor and freelist (if 0, then defaults will be created)
+
+ ACE_Timer_Heap_T (FUNCTOR *upcall_functor = 0, ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
+ // Default constructor. <upcall_functor> is the instance of the
+ // FUNCTOR to be used by the queue. If <upcall_functor> is 0, Timer
+ // Heap will create a default FUNCTOR. <freelist> the freelist of
+ // timer nodes. If 0, then a default freelist will be created. The default
+ // size will be ACE_DEFAULT_TIMERS and there will be no preallocation.
virtual ~ACE_Timer_Heap_T (void);
// Destructor.
@@ -124,31 +141,34 @@ public:
// 0 then the <functor> will be invoked. Returns 1 if cancellation
// succeeded and 0 if the <timer_id> wasn't found.
+ virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK> &iter (void);
+ // Returns a pointer to this <ACE_Timer_Queue>'s iterator.
+
+ ACE_Timer_Node_T <TYPE> *remove_first (void);
+ // Removes the earliest node from the queue and returns it
+
virtual void dump (void) const;
// Dump the state of an object.
protected:
- virtual void reschedule (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *);
+ virtual void reschedule (ACE_Timer_Node_T<TYPE> *);
// Reschedule an "interval" <ACE_Timer_Node>.
- virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK> &iter (void);
- // Returns a pointer to this <ACE_Timer_Queue>'s iterator.
-
- virtual ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *alloc_node (void);
+ virtual ACE_Timer_Node_T<TYPE> *alloc_node (void);
// Factory method that allocates a new node (uses operator new if
// we're *not* preallocating, otherwise uses an internal freelist).
- virtual void free_node (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *);
+ virtual void free_node (ACE_Timer_Node_T<TYPE> *);
// Factory method that frees a previously allocated node (uses
// operatord delete if we're *not* preallocating, otherwise uses an
// internal freelist).
private:
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *remove (size_t index);
+ ACE_Timer_Node_T<TYPE> *remove (size_t index);
// Remove and return the <index>th <ACE_Timer_Node> and restore the
// heap property.
- void insert (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *new_node);
+ void insert (ACE_Timer_Node_T<TYPE> *new_node);
// Insert <new_node> into the heap and restore the heap property.
void grow_heap (void);
@@ -156,17 +176,17 @@ private:
// If preallocation is used, will also double the size of the
// preallocated array of ACE_Timer_Nodes.
- void reheap_up (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *new_node,
+ void reheap_up (ACE_Timer_Node_T<TYPE> *new_node,
size_t index,
size_t parent);
// Restore the heap property, starting at <index>.
- void reheap_down (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *moved_node,
+ void reheap_down (ACE_Timer_Node_T<TYPE> *moved_node,
size_t index,
size_t child);
// Restore the heap property, starting at <index>.
- void copy (int index, ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *moved_node);
+ void copy (int index, ACE_Timer_Node_T<TYPE> *moved_node);
// Copy <moved_node> into the <index> slot of <heap_> and move
// <index> into the corresponding slot in the <timer_id_> array.
@@ -191,7 +211,7 @@ private:
HEAP_ITERATOR iterator_;
// Iterator used to expire timers.
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> **heap_;
+ ACE_Timer_Node_T<TYPE> **heap_;
// Current contents of the Heap, which is organized as a "heap" of
// <ACE_Timer_Node> *'s. In this context, a heap is a "partially
// ordered, almost complete" binary tree, which is stored in an
@@ -211,17 +231,17 @@ private:
// "Pointer" to the first element in the freelist contained within
// the <timer_ids_> array, which is organized as a stack.
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *preallocated_nodes_;
+ ACE_Timer_Node_T<TYPE> *preallocated_nodes_;
// If this is non-0, then we preallocate <max_size_> number of
// <ACE_Timer_Node> objects in order to reduce dynamic allocation
// costs. In auto-growing implementation, this points to the
// last array of nodes allocated.
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *preallocated_nodes_freelist_;
+ ACE_Timer_Node_T<TYPE> *preallocated_nodes_freelist_;
// This points to the head of the <preallocated_nodes_> freelist,
// which is organized as a stack.
- ACE_Unbounded_Set<ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *> preallocated_node_set_;
+ ACE_Unbounded_Set<ACE_Timer_Node_T<TYPE> *> preallocated_node_set_;
// Set of pointers to the arrays of preallocated timer nodes.
// Used to delete the allocated memory when required.
diff --git a/ace/Timer_List.h b/ace/Timer_List.h
index 228a6f21a78..1212985b4b2 100644
--- a/ace/Timer_List.h
+++ b/ace/Timer_List.h
@@ -23,12 +23,12 @@
// compatibility.
typedef ACE_Timer_List_T<ACE_Event_Handler *,
- ACE_Event_Handler_Handle_Timeout_Upcall,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
ACE_SYNCH_RECURSIVE_MUTEX>
ACE_Timer_List;
typedef ACE_Timer_List_Iterator_T<ACE_Event_Handler *,
- ACE_Event_Handler_Handle_Timeout_Upcall,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
ACE_SYNCH_RECURSIVE_MUTEX>
ACE_Timer_List_Iterator;
diff --git a/ace/Timer_List_T.cpp b/ace/Timer_List_T.cpp
index 3aecb92845e..4f16d865763 100644
--- a/ace/Timer_List_T.cpp
+++ b/ace/Timer_List_T.cpp
@@ -1,5 +1,3 @@
-// $Id$
-
#if !defined (ACE_TIMER_LIST_T_C)
#define ACE_TIMER_LIST_T_C
@@ -7,29 +5,58 @@
#include "ace/Timer_List_T.h"
+// Default Constructor
+
template <class TYPE, class FUNCTOR, class LOCK>
-ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_List_Iterator_T (ACE_Timer_List_T<TYPE, FUNCTOR, LOCK> &list)
- : timer_list_ (list)
+ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_List_Iterator_T (ACE_Timer_List_T<TYPE, FUNCTOR, LOCK> &listParm)
+ : timer_list_ (listParm),
+ position_ (NULL)
{
+ // Nothing
}
-template <class TYPE, class FUNCTOR, class LOCK> int
-ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, LOCK>::next (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *&node,
- const ACE_Time_Value &cur_time)
+// Positions the iterator at the node right after the dummy node
+
+template <class TYPE, class FUNCTOR, class LOCK> void
+ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, LOCK>::first (void)
{
- if (this->timer_list_.head_ == 0
- || this->timer_list_.head_->timer_value_ > cur_time)
- return 0;
- else
- {
- node = this->timer_list_.head_;
- this->timer_list_.head_ = this->timer_list_.head_->next_;
- return 1;
- }
+ this->position_ = this->timer_list_.head_->get_next ();
+}
+
+
+// Positions the iterator at the next node in the Timer Queue
+
+template <class TYPE, class FUNCTOR, class LOCK> void
+ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, LOCK>::next (void)
+{
+ // Make sure that if we are at the end, we don't wrap around
+ if (this->position_ != this->timer_list_.head_)
+ this->position_ = this->position_->get_next ();
+}
+
+
+// Returns true when we are at <head_>
+
+template <class TYPE, class FUNCTOR, class LOCK> int
+ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, LOCK>::isdone (void)
+{
+ return this->position_ == this->timer_list_.head_;
+}
+
+
+// Returns the node at <position_> or NULL if we are at the end
+
+template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, LOCK>::item (void)
+{
+ if (this->position_ != this->timer_list_.head_)
+ return this->position_;
+ return NULL;
}
-ACE_ALLOC_HOOK_DEFINE(ACE_Timer_List_T)
+
+// Return our instance of the iterator
template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK> &
ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::iter (void)
@@ -37,271 +64,234 @@ ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::iter (void)
return this->iterator_;
}
+
// Create an empty list.
template <class TYPE, class FUNCTOR, class LOCK>
-ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_List_T (FUNCTOR *upcall_functor)
- : ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK> (upcall_functor),
- head_ (0),
+ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_List_T (FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
+ : ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK> (upcall_functor, freelist),
+ head_ (new ACE_Timer_Node_T<TYPE>),
iterator_ (*this),
timer_id_ (0)
{
- ACE_TRACE ("ACE_Timer_List::ACE_Timer_List");
+ ACE_TRACE ("ACE_Timer_List_T::ACE_Timer_List");
+ this->head_->set_next (this->head_);
+ this->head_->set_prev (this->head_);
}
-// Checks if list is empty.
+// Checks if list is empty.
template <class TYPE, class FUNCTOR, class LOCK> int
ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::is_empty (void) const
{
- ACE_TRACE ("ACE_Timer_List::is_empty");
- return this->head_ == 0;
-}
-
-template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *
-ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::alloc_node (void)
-{
- return new ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>;
+ ACE_TRACE ("ACE_Timer_List_T::is_empty");
+ return this->head_->get_next () == this->head_;
}
-template <class TYPE, class FUNCTOR, class LOCK> void
-ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::free_node (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *node)
-{
- delete node;
-}
// Returns earliest time in a non-empty list.
-
template <class TYPE, class FUNCTOR, class LOCK> const ACE_Time_Value &
ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::earliest_time (void) const
{
- ACE_TRACE ("ACE_Timer_List::earliest_time");
- return this->head_->timer_value_;
+ ACE_TRACE ("ACE_Timer_List_T::earliest_time");
+ return this->head_->get_next ()->get_timer_value ();
}
+
// Remove all remaining items in the list.
template <class TYPE, class FUNCTOR, class LOCK>
ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::~ACE_Timer_List_T (void)
{
- ACE_TRACE ("ACE_Timer_List::~ACE_Timer_List");
+ ACE_TRACE ("ACE_Timer_List_T::~ACE_Timer_List_T");
ACE_MT (ACE_GUARD (LOCK, ace_mon, this->mutex_));
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *curr = this->head_;
+ ACE_Timer_Node_T<TYPE> *curr = this->head_->get_next ();
- while (curr != 0)
+ while (curr != this->head_)
{
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *next = curr->next_;
+ ACE_Timer_Node_T<TYPE> *next = curr->get_next ();
+ this->upcall_functor ().deletion (*this, next->get_type (), next->get_act ());
this->free_node (curr);
curr = next;
}
+
+ // delete the dummy node
+ delete this->head_;
}
template <class TYPE, class FUNCTOR, class LOCK> void
ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::dump (void) const
{
- ACE_TRACE ("ACE_Timer_List::dump");
+ ACE_TRACE ("ACE_Timer_List_T::dump");
ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
- ACE_DEBUG ((LM_DEBUG, "\nhead_ = %d", this->head_));
+ size_t count = 0;
+ ACE_Timer_Node_T<TYPE> *curr = this->head_->get_next ();
+ while (curr != this->head_)
+ {
+ count++;
+ curr = curr->get_next ();
+ }
+ ACE_DEBUG ((LM_DEBUG, "\nsize_ = %d", count));
ACE_DEBUG ((LM_DEBUG, "\ntimer_id_ = %d", this->timer_id_));
ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
}
+
// Reschedule a periodic timer. This function must be called with the
// mutex lock held.
-
template <class TYPE, class FUNCTOR, class LOCK> void
-ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::reschedule (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *expired)
+ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::reschedule (ACE_Timer_Node_T<TYPE> *expired)
{
- ACE_TRACE ("ACE_Timer_List::reschedule");
- if (this->is_empty ()
- || expired->timer_value_ < this->earliest_time ())
- {
- expired->next_ = this->head_;
- this->head_ = expired;
- }
- else
- {
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *prev = this->head_;
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *after = this->head_->next_;
+ ACE_TRACE ("ACE_Timer_List_T::reschedule");
- // Locate the proper position in the queue.
+ ACE_Timer_Node_T<TYPE> *after = this->head_->get_next ();
- while (after != 0
- && expired->timer_value_ > after->timer_value_)
- {
- prev = after;
- after = after->next_;
- }
+ // Locate the proper position in the queue.
- expired->next_ = after;
- prev->next_ = expired;
- }
+ while (after != this->head_
+ && expired->get_timer_value () > after->get_timer_value ())
+ after = after->get_next ();
+
+ expired->set_next (after);
+ expired->set_prev (after->get_prev ());
+ after->get_prev ()->set_next (expired);
+ after->set_prev (expired);
}
+
// Insert a new handler that expires at time future_time; if interval
// is > 0, the handler will be reinvoked periodically.
-
template <class TYPE, class FUNCTOR, class LOCK> long
ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::schedule (const TYPE &type,
const void *act,
const ACE_Time_Value &future_time,
const ACE_Time_Value &interval)
{
- ACE_TRACE ("ACE_Timer_List::schedule");
+ ACE_TRACE ("ACE_Timer_List_T::schedule");
ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, this->mutex_, -1));
- // Increment the sequence number (it will wrap around).
- long timer_id = this->timer_id ();
-
- if (this->is_empty () || future_time < this->earliest_time ())
- {
- // Place at the beginning of the list.
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *temp = this->alloc_node ();
-
- // Use operator placement new.
- this->head_ = new (temp) ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> (type,
- act,
- future_time,
- interval,
- this->head_,
- timer_id);
- return timer_id;
- }
-
// Place in the middle of the list where it belongs (i.e., sorted in
// ascending order of absolute time to expire).
- else
- {
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *prev = this->head_;
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *after = this->head_->next_;
-
- while (after != 0 && future_time > after->timer_value_)
- {
- prev = after;
- after = after->next_;
- }
+ ACE_Timer_Node_T<TYPE> *after = this->head_->get_next ();
+
+ while (after != this->head_ && future_time > after->get_timer_value ())
+ after = after->get_next ();
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *temp = this->alloc_node ();
+ ACE_Timer_Node_T<TYPE> *temp = this->alloc_node ();
- // Use operator placement new.
- prev->next_ = new (temp) ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> (type,
- act,
- future_time,
- interval,
- after,
- timer_id);
- return timer_id;
- }
-}
+ temp->set (type,
+ act,
+ future_time,
+ interval,
+ after->get_prev (),
+ after,
+ (long) temp);
+ after->get_prev ()->set_next (temp);
+ after->set_prev (temp);
-template <class TYPE, class FUNCTOR, class LOCK> int
-ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::timer_id (void)
-{
- // We need to truncate this to <int> for backwards compatibility.
- int tid = this->timer_id_++;
-
- // Make sure this never == -1
- if (tid == -1)
- tid = 0;
-
- return tid;
+ return (long) temp;
}
+
// Locate and remove the single <ACE_Event_Handler> with a value of
// <timer_id> from the timer queue.
-
template <class TYPE, class FUNCTOR, class LOCK> int
ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::cancel (long timer_id,
const void **act,
int dont_call)
{
- ACE_TRACE ("ACE_Timer_List::cancel");
+ ACE_TRACE ("ACE_Timer_List_T::cancel");
ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, this->mutex_, -1));
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *prev = 0;
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *curr = 0;
-
- // Try to locate the ACE_Timer_Node that matches the timer_id.
-
- for (curr = this->head_;
- curr != 0 && curr->timer_id_ != timer_id;
- curr = curr->next_)
- prev = curr;
-
- if (curr != 0)
+ // Make sure we are getting a valid <timer_id>, not an error
+ // returned by schedule ()
+ if (timer_id == -1)
+ return 0;
+
+ ACE_Timer_Node_T<TYPE> *node = (ACE_Timer_Node_T<TYPE> *) timer_id;
+
+ // Check to see if the node looks like a true ACE_Timer_Node_T<TYPE>
+ if (timer_id == node->get_timer_id ())
{
- if (prev == 0)
- this->head_ = curr->next_;
- else
- prev->next_ = curr->next_;
-
+ node->get_next ()->set_prev (node->get_prev ());
+ node->get_prev ()->set_next (node->get_next ());
+
if (act != 0)
- *act = curr->act_;
+ *act = node->get_act ();
if (dont_call == 0)
- this->upcall_functor_.cancellation (*this, curr->type_);
- this->free_node (curr);
+ this->upcall_functor ().cancellation (*this, node->get_type ());
+
+ this->free_node (node);
return 1;
}
- else
- return 0;
+
+ // Wasn't valid
+ return 0;
}
-// Locate and remove all values of <handler> from the timer queue.
+// Locate and remove all values of <handler> from the timer queue.
template <class TYPE, class FUNCTOR, class LOCK> int
ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::cancel (const TYPE &type,
int dont_call)
{
- ACE_TRACE ("ACE_Timer_List::cancel");
+ ACE_TRACE ("ACE_Timer_List_T::cancel");
ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, this->mutex_, -1));
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *prev = 0;
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *curr = this->head_;
+ ACE_Timer_Node_T<TYPE> *curr = this->head_->get_next ();
int number_of_cancellations = 0;
- while (curr != 0)
+ while (curr != this->head_)
{
- if (curr->type_ == type)
+ if (curr->get_type () == type)
{
number_of_cancellations++;
if (dont_call == 0
&& number_of_cancellations == 1)
- this->upcall_functor_.cancellation (*this, curr->type_);
-
- if (prev == 0)
- {
- this->head_ = curr->next_;
- this->free_node (curr);
- curr = this->head_;
- }
- else
- {
- prev->next_ = curr->next_;
- this->free_node (curr);
- curr = prev->next_;
- }
+ this->upcall_functor ().cancellation (*this, curr->get_type ());
+
+ curr->get_prev ()->set_next (curr->get_next ());
+ curr->get_next ()->set_prev (curr->get_prev ());
+ ACE_Timer_Node_T<TYPE> *temp = curr;
+ curr = curr->get_next ();
+ this->free_node (temp);
}
else
- {
- prev = curr;
- curr = curr->next_;
- }
+ curr = curr->get_next ();
}
return number_of_cancellations;
}
+
+// Removes the first node on the list and returns it.
+
+template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>::remove_first (void)
+{
+ ACE_TRACE ("ACE_Timer_List_T::remove_first");
+
+ // remove the node and fix the pointers
+ ACE_Timer_Node_T<TYPE> *temp = this->head_->get_next ();
+ this->head_->set_next (temp->get_next ());
+ temp->get_next ()->set_prev (this->head_);
+
+ return temp;
+}
+
+
#endif /* ACE_TIMER_LIST_T_C */
diff --git a/ace/Timer_List_T.h b/ace/Timer_List_T.h
index b164fff5aa6..4364d9eb6ae 100644
--- a/ace/Timer_List_T.h
+++ b/ace/Timer_List_T.h
@@ -1,6 +1,4 @@
/* -*- C++ -*- */
-// $Id$
-
// ============================================================================
//
// = LIBRARY
@@ -26,26 +24,33 @@ class ACE_Timer_List_T;
template <class TYPE, class FUNCTOR, class LOCK>
class ACE_Timer_List_Iterator_T : public ACE_Timer_Queue_Iterator_T <TYPE, FUNCTOR, LOCK>
// = TITLE
- // Iterates over an <ACE_Timer_Queue>.
+ // Iterates over an <ACE_Timer_List>.
//
// = DESCRIPTION
- // This is a special type of iterator that "advances" by moving
- // the head of the timer queue up by one every time.
+ // This is a generic iterator that can be used to visit every
+ // node of a timer queue.
{
public:
ACE_Timer_List_Iterator_T (ACE_Timer_List_T<TYPE, FUNCTOR, LOCK> &);
// Constructor.
- virtual int next (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *&timer_node,
- const ACE_Time_Value &cur_time);
- // Pass back the next <timer_node> that hasn't been seen yet, if its
- // <time_value_> <= <cur_time>. In addition, moves the timer queue
- // forward by one node. Returns 0 when all <timer_nodes> have been
- // seen, else 1.
+ virtual void first (void);
+ // Positions the iterator at the earliest node in the Timer Queue
+
+ virtual void next (void);
+ // Positions the iterator at the next node in the Timer Queue
+
+ virtual int isdone (void);
+ // Returns true when there are no more nodes in the sequence
+
+ virtual ACE_Timer_Node_T<TYPE> *item (void);
+ // Returns the node at the current position in the sequence
protected:
ACE_Timer_List_T<TYPE, FUNCTOR, LOCK> &timer_list_;
// Pointer to the <ACE_Timer_List> that we are iterating over.
+
+ ACE_Timer_Node_T<TYPE> *position_;
};
template <class TYPE, class FUNCTOR, class LOCK>
@@ -79,10 +84,12 @@ public:
// Type inherited from
// = Initialization and termination methods.
- ACE_Timer_List_T (FUNCTOR *upcall_functor = 0);
+ ACE_Timer_List_T (FUNCTOR *upcall_functor = 0,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
// Default constructor. <upcall_functor> is the instance of the
// FUNCTOR to be used by the list. If <upcall_functor> is 0, a
- // default FUNCTOR will be created.
+ // default FUNCTOR will be created. <freelist> the freelist of
+ // timer nodes. If 0, then a default freelist will be created.
virtual ~ACE_Timer_List_T (void);
// Destructor
@@ -127,31 +134,29 @@ public:
// 0 then the <functor> will be invoked. Returns 1 if cancellation
// succeeded and 0 if the <timer_id> wasn't found.
+ virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK> &iter (void);
+ // Returns a pointer to this <ACE_Timer_Queue>'s iterator.
+
+ virtual ACE_Timer_Node_T<TYPE> *remove_first (void);
+ // Removes the earliest node from the queue and returns it
+
virtual void dump (void) const;
// Dump the state of an object.
+ virtual void reschedule (ACE_Timer_Node_T<TYPE> *);
+ // Reschedule an "interval" <ACE_Timer_Node>. This should be private
+ // but for now it needs to be public for <ACE_Timer_Hash_T>
+
protected:
- virtual ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *alloc_node (void);
+/* virtual ACE_Timer_Node_T<TYPE> *alloc_node (void);
// Factory method that allocates a new node (uses operator new).
- virtual void free_node (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *);
+ virtual void free_node (ACE_Timer_Node_T<TYPE> *);
// Factory method that frees a previously allocated node (uses
// operator delete).
-
+*/
private:
- int timer_id (void);
- // Returns a timer id that uniquely identifies this timer. This id
- // can be used to cancel a timer via the <cancel (int)> method. The
- // timer id returned from this method will never == -1 to avoid
- // conflicts with other failure return values.
-
- virtual void reschedule (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *);
- // Reschedule an "interval" <ACE_Timer_Node>.
-
- virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK> &iter (void);
- // Returns a pointer to this <ACE_Timer_Queue>'s iterator.
-
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *head_;
+ ACE_Timer_Node_T<TYPE> *head_;
// Pointer to linked list of <ACE_Timer_Handles>.
LIST_ITERATOR iterator_;
diff --git a/ace/Timer_Queue.cpp b/ace/Timer_Queue.cpp
index 259f63dea82..dca4e89d916 100644
--- a/ace/Timer_Queue.cpp
+++ b/ace/Timer_Queue.cpp
@@ -1,4 +1,5 @@
-// $Id$
+#if !defined (ACE_TIMER_QUEUE_C)
+#define ACE_TIMER_QUEUE_C
#define ACE_BUILD_DLL
@@ -7,13 +8,14 @@
#include "ace/Timer_Heap_T.h"
#include "ace/Timer_List_T.h"
#include "ace/Timer_Wheel_T.h"
+#include "ace/Timer_Hash_T.h"
#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */
-int
-ACE_Event_Handler_Handle_Timeout_Upcall::timeout (TIMER_QUEUE &timer_queue,
- ACE_Event_Handler *handler,
- const void *act,
- const ACE_Time_Value &cur_time)
+template <class LOCK> int
+ACE_Event_Handler_Handle_Timeout_Upcall<LOCK>::timeout (TIMER_QUEUE &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)
@@ -22,9 +24,9 @@ ACE_Event_Handler_Handle_Timeout_Upcall::timeout (TIMER_QUEUE &timer_queue,
return 0;
}
-int
-ACE_Event_Handler_Handle_Timeout_Upcall::cancellation (TIMER_QUEUE &timer_queue,
- ACE_Event_Handler *handler)
+template <class LOCK> int
+ACE_Event_Handler_Handle_Timeout_Upcall<LOCK>::cancellation (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler)
{
ACE_UNUSED_ARG (timer_queue);
@@ -34,6 +36,21 @@ ACE_Event_Handler_Handle_Timeout_Upcall::cancellation (TIMER_QUEUE &timer_queue,
return 0;
}
+template <class LOCK> int
+ACE_Event_Handler_Handle_Timeout_Upcall<LOCK>::deletion (TIMER_QUEUE &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;
+}
+
+
#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION)
template class ACE_Unbounded_Set<ACE_Timer_Node_T<ACE_Event_Handler *, ACE_Event_Handler_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX> *>;
template class ACE_Node<ACE_Timer_Node_T<ACE_Event_Handler *, ACE_Event_Handler_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX> *>;
@@ -47,4 +64,8 @@ template class ACE_Timer_Queue_T<ACE_Event_Handler *, ACE_Event_Handler_Handle_T
template class ACE_Timer_Queue_Iterator_T<ACE_Event_Handler *, ACE_Event_Handler_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX>;
template class ACE_Timer_Wheel_T<ACE_Event_Handler *, ACE_Event_Handler_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX>;
template class ACE_Timer_Wheel_Iterator_T<ACE_Event_Handler *, ACE_Event_Handler_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX>;
+template class ACE_Timer_Hash_T<ACE_Event_Handler *, ACE_Event_Handler_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX>;
+template class ACE_Timer_Hash_Iterator_T<ACE_Event_Handler *, ACE_Event_Handler_Handle_Timeout_Upcall, ACE_SYNCH_RECURSIVE_MUTEX>;
#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */
+
+#endif /* ACE_TIMER_QUEUE_C */
diff --git a/ace/Timer_Queue.h b/ace/Timer_Queue.h
index 42bf2fb5248..a0de5dbd5dc 100644
--- a/ace/Timer_Queue.h
+++ b/ace/Timer_Queue.h
@@ -1,5 +1,4 @@
/* -*- C++ -*- */
-// $Id$
// ============================================================================
//
@@ -20,7 +19,8 @@
#include "ace/Synch.h"
#include "ace/Timer_Queue_T.h"
-class ACE_Export ACE_Event_Handler_Handle_Timeout_Upcall
+template <class LOCK>
+class ACE_Event_Handler_Handle_Timeout_Upcall
// = TITLE
// Functor for Timer_Queues.
//
@@ -30,8 +30,8 @@ class ACE_Export ACE_Event_Handler_Handle_Timeout_Upcall
{
public:
typedef ACE_Timer_Queue_T<ACE_Event_Handler *,
- ACE_Event_Handler_Handle_Timeout_Upcall,
- ACE_SYNCH_RECURSIVE_MUTEX>
+ ACE_Event_Handler_Handle_Timeout_Upcall<LOCK>,
+ LOCK>
TIMER_QUEUE;
int timeout (TIMER_QUEUE &timer_queue,
@@ -43,24 +43,37 @@ public:
int cancellation (TIMER_QUEUE &timer_queue,
ACE_Event_Handler *handler);
// This method is called when the timer is canceled
+
+ int deletion (TIMER_QUEUE &timer_queue,
+ ACE_Event_Handler *handler,
+ const void *arg);
+ // This method is called when the timer queue is destroyed and
+ // the timer is still contained in it
};
// The following typedef are here for ease of use and backward
// compatibility.
-typedef ACE_Timer_Node_T<ACE_Event_Handler *,
- ACE_Event_Handler_Handle_Timeout_Upcall,
- ACE_SYNCH_RECURSIVE_MUTEX>
+typedef ACE_Timer_Node_T<ACE_Event_Handler *>
ACE_Timer_Node;
typedef ACE_Timer_Queue_T<ACE_Event_Handler *,
- ACE_Event_Handler_Handle_Timeout_Upcall,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
ACE_SYNCH_RECURSIVE_MUTEX>
ACE_Timer_Queue;
typedef ACE_Timer_Queue_Iterator_T<ACE_Event_Handler *,
- ACE_Event_Handler_Handle_Timeout_Upcall,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
ACE_SYNCH_RECURSIVE_MUTEX>
ACE_Timer_Queue_Iterator;
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Timer_Queue.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Timer_Queue.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
#endif /* ACE_TIMER_QUEUE_H */
diff --git a/ace/Timer_Queue.i b/ace/Timer_Queue.i
new file mode 100644
index 00000000000..41e4324e61e
--- /dev/null
+++ b/ace/Timer_Queue.i
@@ -0,0 +1,22 @@
+/* -*- C++ -*- */
+
+template <class TYPE, class FUNCTOR> ACE_INLINE void
+ACE_Timer_Queue_T<TYPE, FUNCTOR>::timer_skew (const ACE_Time_Value &skew)
+{
+ timer_skew_ = skew;
+}
+
+template <class TYPE, class FUNCTOR> ACE_INLINE const ACE_Time_Value &
+ACE_Timer_Queue_T<TYPE, FUNCTOR>::timer_skew (void) const
+{
+ return timer_skew_;
+}
+
+template <class TYPE, class FUNCTOR> ACE_INLINE int
+ACE_Timer_Queue_T<TYPE, FUNCTOR>::expire (void)
+{
+ if (!this->is_empty ())
+ return this->expire (this->gettimeofday () + timer_skew_);
+ else
+ return 0;
+}
diff --git a/ace/Timer_Queue_T.cpp b/ace/Timer_Queue_T.cpp
index cfe8060ddfa..c514a15b128 100644
--- a/ace/Timer_Queue_T.cpp
+++ b/ace/Timer_Queue_T.cpp
@@ -1,6 +1,3 @@
-// Timer_Queue_T.cpp
-// $Id$
-
#if !defined (ACE_TIMER_QUEUE_T_C)
#define ACE_TIMER_QUEUE_T_C
@@ -12,12 +9,10 @@
#include "ace/Timer_Queue_T.i"
#endif /* __ACE_INLINE__ */
-ACE_ALLOC_HOOK_DEFINE(ACE_Timer_Node_T)
-
-template <class TYPE, class FUNCTOR, class LOCK> void
-ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>::dump (void) const
+template <class TYPE> void
+ACE_Timer_Node_T<TYPE>::dump (void) const
{
- ACE_TRACE ("ACE_Timer_Node::dump");
+ ACE_TRACE ("ACE_Timer_Node_T::dump");
ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
// ACE_DEBUG ((LM_DEBUG, "\type_ = %x", this->type_));
ACE_DEBUG ((LM_DEBUG, "\nact_ = %x", this->act_));
@@ -29,50 +24,12 @@ ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>::dump (void) const
ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
}
-template <class TYPE, class FUNCTOR, class LOCK>
-ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Node_T (void)
-{
- ACE_TRACE ("ACE_Timer_Node::ACE_Timer_Node");
-}
-
-template <class TYPE, class FUNCTOR, class LOCK>
-ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Node_T (const TYPE &type,
- const void *a,
- const ACE_Time_Value &t,
- const ACE_Time_Value &i,
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *n,
- long timer_id)
- : type_ (type),
- act_ (a),
- timer_value_ (t),
- interval_ (i),
- prev_ (0),
- next_ (n),
- timer_id_ (timer_id)
-{
- ACE_TRACE ("ACE_Timer_Node::ACE_Timer_Node");
-}
-
-template <class TYPE, class FUNCTOR, class LOCK>
-ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Node_T (const TYPE &type,
- const void *a,
- const ACE_Time_Value &t,
- const ACE_Time_Value &i,
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *p,
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *n,
- long timer_id)
- : type_ (type),
- act_ (a),
- timer_value_ (t),
- interval_ (i),
- prev_ (p),
- next_ (n),
- timer_id_ (timer_id)
+template <class TYPE>
+ACE_Timer_Node_T<TYPE>::ACE_Timer_Node_T (void)
{
- ACE_TRACE ("ACE_Timer_Node::ACE_Timer_Node");
+ ACE_TRACE ("ACE_Timer_Node_T::ACE_Timer_Node_T");
}
-
template <class TYPE, class FUNCTOR, class LOCK>
ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Queue_Iterator_T (void)
{
@@ -94,7 +51,7 @@ ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK>::~ACE_Timer_Queue_Iterator_T (vo
template <class TYPE, class FUNCTOR, class LOCK> ACE_Time_Value *
ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::calculate_timeout (ACE_Time_Value *max_wait_time)
{
- ACE_TRACE ("ACE_Timer_List::calculate_timeout");
+ ACE_TRACE ("ACE_Timer_Queue_T::calculate_timeout");
ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, this->mutex_, max_wait_time));
if (this->is_empty ())
@@ -131,7 +88,7 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::calculate_timeout (ACE_Time_Value *max_w
template <class TYPE, class FUNCTOR, class LOCK> void
ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::dump (void) const
{
- ACE_TRACE ("ACE_Timer_Queue::dump");
+ ACE_TRACE ("ACE_Timer_Queue_T::dump");
ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
this->timeout_.dump ();
this->timer_skew_.dump ();
@@ -139,23 +96,41 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::dump (void) const
}
template <class TYPE, class FUNCTOR, class LOCK>
-ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Queue_T (FUNCTOR *upcall_functor)
+ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Queue_T (FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
: gettimeofday_ (ACE_OS::gettimeofday),
- upcall_functor_ (upcall_functor == 0 ? *(new FUNCTOR) : *upcall_functor),
+ upcall_functor_ (upcall_functor == 0 ? new FUNCTOR : upcall_functor),
delete_upcall_functor_ (upcall_functor == 0),
- timer_skew_ (0, ACE_TIMER_SKEW)
+ timer_skew_ (0, ACE_TIMER_SKEW),
+ free_list_ (freelist == 0 ? new ACE_Locked_Free_List<ACE_Timer_Node_T <TYPE>, ACE_Null_Mutex> : freelist),
+ delete_free_list_ (freelist == 0)
{
- ACE_TRACE ("ACE_Timer_Queue::ACE_Timer_Queue");
+ ACE_TRACE ("ACE_Timer_Queue_T::ACE_Timer_Queue_T");
}
template <class TYPE, class FUNCTOR, class LOCK>
ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::~ACE_Timer_Queue_T (void)
{
- // Cleanup the functor on the way out
- if (delete_upcall_functor_)
- delete &this->upcall_functor_;
+ 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 LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::alloc_node (void)
+{
+ return this->free_list_->remove ();
+}
- ACE_TRACE ("ACE_Timer_Queue::~ACE_Timer_Queue");
+template <class TYPE, class FUNCTOR, class LOCK> void
+ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::free_node (ACE_Timer_Node_T<TYPE> *node)
+{
+ this->free_list_->add (node);
}
// Run the <handle_timeout> method for all Timers whose values are <=
@@ -164,32 +139,31 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::~ACE_Timer_Queue_T (void)
template <class TYPE, class FUNCTOR, class LOCK> int
ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::expire (const ACE_Time_Value &cur_time)
{
- ACE_TRACE ("ACE_Timer_List::expire");
+ ACE_TRACE ("ACE_Timer_Queue_T::expire");
ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, this->mutex_, -1));
int number_of_timers_expired = 0;
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *expired;
+ ACE_Timer_Node_T<TYPE> *expired;
// Keep looping while there are timers remaining and the earliest
// timer is <= the <cur_time> passed in to the method.
- for (ITERATOR &iter = this->iter ();
- iter.next (expired, cur_time) != 0;
- )
+ while (this->earliest_time () <= cur_time)
{
- TYPE &type = expired->type_;
- const void *act = expired->act_;
+ expired = this->remove_first ();
+ TYPE &type = expired->get_type ();
+ const void *act = expired->get_act ();
int reclaim = 1;
// Check if this is an interval timer.
- if (expired->interval_ > ACE_Time_Value::zero)
+ if (expired->get_interval () > ACE_Time_Value::zero)
{
// Make sure that we skip past values that have already
// "expired".
do
- expired->timer_value_ += expired->interval_;
- while (expired->timer_value_ <= cur_time);
+ 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.
@@ -205,15 +179,12 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::expire (const ACE_Time_Value &cur_time)
this->free_node (expired);
number_of_timers_expired++;
+
+ if (this->is_empty ())
+ break;
}
return number_of_timers_expired;
}
-template <class TYPE, class FUNCTOR, class LOCK> LOCK &
-ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::mutex (void)
-{
- return this->mutex_;
-}
-
#endif /* ACE_TIMER_QUEUE_T_C*/
diff --git a/ace/Timer_Queue_T.h b/ace/Timer_Queue_T.h
index 538dd267c45..a2f3d978cd2 100644
--- a/ace/Timer_Queue_T.h
+++ b/ace/Timer_Queue_T.h
@@ -1,5 +1,4 @@
/* -*- C++ -*- */
-// $Id$
// ============================================================================
//
@@ -10,7 +9,7 @@
// Timer_Queue_T.h
//
// = AUTHOR
-// Doug Schmidt and Irfan Pyarali
+// Doug Schmidt, Irfan Pyarali, and Darrell Brunsch
//
// ============================================================================
@@ -18,67 +17,85 @@
#define ACE_TIMER_QUEUE_T_H
#include "ace/Time_Value.h"
+#include "ace/Free_List.h"
-// Forward declarations.
-template <class TYPE, class FUNCTOR, class LOCK>
-class ACE_Timer_Queue_T;
+// This should be nested within the ACE_Timer_Queue class but some C++
+// compilers still don't like this...
-template <class TYPE, class FUNCTOR, class LOCK>
-class ACE_Timer_List_T;
+template <class TYPE>
+class ACE_Timer_Node_T
+ // = TITLE
+ // Maintains the state associated with a Timer entry.
+{
+public:
+ ACE_Timer_Node_T ();
+ // Default constructor
+
+ void set (const TYPE &type,
+ const void *a,
+ const ACE_Time_Value &t,
+ const ACE_Time_Value &i,
+ ACE_Timer_Node_T<TYPE> *n,
+ long timer_id);
+ // singly linked list
+
+ void set (const TYPE &type,
+ const void *a,
+ const ACE_Time_Value &t,
+ const ACE_Time_Value &i,
+ ACE_Timer_Node_T<TYPE> *p,
+ ACE_Timer_Node_T<TYPE> *n,
+ long timer_id);
+ // doubly linked list version
+
+ // = Accessors
+
+ TYPE &get_type (void);
+ // get the type
+
+ void set_type (TYPE &type);
+ // set the type
-template <class TYPE, class FUNCTOR, class LOCK>
-class ACE_Timer_List_Iterator_T;
+ const void *get_act (void);
+ // get the act
-template <class TYPE, class FUNCTOR, class LOCK>
-class ACE_Timer_Heap_T;
+ void set_act (void *act);
+ // set the act
-template <class TYPE, class FUNCTOR, class LOCK>
-class ACE_Timer_Heap_Iterator_T;
+ ACE_Time_Value &get_timer_value (void);
+ // get the timer value
-template <class TYPE, class FUNCTOR, class LOCK>
-class ACE_Timer_Wheel_T;
+ void set_timer_value (ACE_Time_Value timer_value);
+ // set the timer value
-template <class TYPE, class FUNCTOR, class LOCK>
-class ACE_Timer_Wheel_Iterator_T;
+ ACE_Time_Value &get_interval (void);
+ // get the timer interval
-// This should be nested within the ACE_Timer_Queue class but some C++
-// compilers still don't like this...
+ void set_interval (ACE_Time_Value interval);
+ // set the timer interval
-template <class TYPE, class FUNCTOR, class LOCK>
-class ACE_Timer_Node_T
- // = TITLE
- // Maintains the state associated with a Timer entry.
-{
- // = The use of friends should be replaced with accessors...
- friend class ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>;
- friend class ACE_Timer_List_T<TYPE, FUNCTOR, LOCK>;
- friend class ACE_Timer_List_Iterator_T<TYPE, FUNCTOR, LOCK>;
- friend class ACE_Timer_Heap_T<TYPE, FUNCTOR, LOCK>;
- friend class ACE_Timer_Heap_Iterator_T<TYPE, FUNCTOR, LOCK>;
- friend class ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>;
- friend class ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, LOCK>;
-
- // = Initialization methods.
- ACE_Timer_Node_T (const TYPE &type,
- const void *a,
- const ACE_Time_Value &t,
- const ACE_Time_Value &i,
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *n,
- long timer_id);
- // Constructor.
+ ACE_Timer_Node_T<TYPE> *get_prev (void);
+ // get the previous pointer
+
+ void set_prev (ACE_Timer_Node_T<TYPE> *prev);
+ // set the previous pointer
+
+ ACE_Timer_Node_T<TYPE> *get_next (void);
+ // get the next pointer
- ACE_Timer_Node_T (const TYPE &type,
- const void *a,
- const ACE_Time_Value &t,
- const ACE_Time_Value &i,
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *p,
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *n,
- long timer_id);
- // Constructor for the doubly linked list version.
+ void set_next (ACE_Timer_Node_T<TYPE> *next);
+ // set the next pointer
+
+ long get_timer_id (void);
+ // get the timer_id
+
+ void set_timer_id (long timer_id);
+ // set the timer_id
+ void dump (void) const;
+ // Dump the state of an TYPE.
- ACE_Timer_Node_T (void);
- // Default constructor.
+private:
TYPE type_;
// Type of object stored in the Queue
@@ -93,33 +110,29 @@ class ACE_Timer_Node_T
// If this is a periodic timer this holds the time until the next
// timeout.
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *prev_;
+ ACE_Timer_Node_T<TYPE> *prev_;
// Pointer to previous timer.
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *next_;
+ ACE_Timer_Node_T<TYPE> *next_;
// Pointer to next timer.
long timer_id_;
// Id of this timer (used to cancel timers before they expire).
-
- ACE_ALLOC_HOOK_DECLARE;
- // Declare the dynamic allocation hooks.
-
- void dump (void) const;
- // Dump the state of an TYPE.
};
template <class TYPE, class FUNCTOR, class LOCK>
class ACE_Timer_Queue_Iterator_T
// = TITLE
- // Generic interfae for iterating over a subclass of
+ // Generic interface for iterating over a subclass of
// <ACE_Timer_Queue>.
//
// = DESCRIPTION
- // This is a special type of iterator that "advances" by moving
- // the head of the timer queue up by one every time.
+ // This is a generic iterator that can be used to visit every
+ // node of a timer queue. Be aware that it isn't guaranteed
+ // that the transversal will be in order of timeout values.
{
public:
+
// = Initialization and termination methods.
ACE_Timer_Queue_Iterator_T (void);
// Constructor.
@@ -127,12 +140,17 @@ public:
virtual ~ACE_Timer_Queue_Iterator_T (void);
// Destructor.
- virtual int next (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *&timer_node,
- const ACE_Time_Value &cur_time) = 0;
- // Pass back the next <timer_node> that hasn't been seen yet, if its
- // <time_value_> <= <cur_time>. In addition, moves the timer queue
- // forward by one node. Returns 0 when all <timer_nodes> have been
- // seen, else 1.
+ virtual void first (void) = 0;
+ // Positions the iterator at the earliest node in the Timer Queue
+
+ virtual void next (void) = 0;
+ // Positions the iterator at the next node in the Timer Queue
+
+ virtual int isdone (void) = 0;
+ // Returns true when there are no more nodes in the sequence
+
+ virtual ACE_Timer_Node_T<TYPE> *item (void) = 0;
+ // Returns the node at the current position in the sequence
};
template <class TYPE, class FUNCTOR, class LOCK>
@@ -146,14 +164,17 @@ class ACE_Timer_Queue_T
// and <ACE_Timer_Heap>.
{
public:
+
typedef ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK> ITERATOR;
// Type of Iterator
// = Initialization and termination methods.
- ACE_Timer_Queue_T (FUNCTOR *upcall_functor = 0);
+ ACE_Timer_Queue_T (FUNCTOR *upcall_functor = 0,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
// Default constructor. <upcall_functor> is the instance of the
// FUNCTOR to be used by the queue. If <upcall_functor> is 0, Timer
- // Queue will create a default FUNCTOR.
+ // Queue will create a default FUNCTOR. <freelist> the freelist of
+ // timer nodes. If 0, then a default freelist will be created.
virtual ~ACE_Timer_Queue_T (void);
// Destructor - make virtual for proper destruction of inherited
@@ -232,45 +253,51 @@ public:
FUNCTOR &upcall_functor (void);
// Accessor to the upcall functor
+ virtual ITERATOR &iter (void) = 0;
+ // Returns a pointer to this <ACE_Timer_Queue>'s iterator.
+
+ virtual ACE_Timer_Node_T<TYPE> *remove_first (void) = 0;
+ // Removes the earliest node from the queue and returns it
+
virtual void dump (void) const;
// Dump the state of a object.
- ACE_ALLOC_HOOK_DECLARE;
- // Declare the dynamic allocation hooks.
-
protected:
-
virtual void upcall (TYPE &type,
const void *act,
const ACE_Time_Value &cur_time);
// This method will call the <functor> with the <type>, <act> and
// <time>
- virtual void reschedule (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *) = 0;
+ virtual void reschedule (ACE_Timer_Node_T<TYPE> *) = 0;
// Reschedule an "interval" <ACE_Timer_Node>.
- virtual ITERATOR &iter (void) = 0;
- // Returns a pointer to this <ACE_Timer_Queue>'s iterator.
-
- virtual ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *alloc_node (void) = 0;
+ virtual ACE_Timer_Node_T<TYPE> *alloc_node (void);
// Factory method that allocates a new node.
- virtual void free_node (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *) = 0;
+ virtual void free_node (ACE_Timer_Node_T<TYPE> *);
// Factory method that frees a previously allocated node.
LOCK mutex_;
// Synchronization variable for <ACE_Timer_Queue>.
+ ACE_Free_List<ACE_Timer_Node_T<TYPE> > *free_list_;
+ // Class that implements a free list
+
ACE_Time_Value (*gettimeofday_)(void);
// Pointer to function that returns the current time of day.
- FUNCTOR &upcall_functor_;
+ FUNCTOR *upcall_functor_;
// Upcall functor
int delete_upcall_functor_;
// To delete or not to delete is the question?
+ int delete_free_list_;
+ // Flag to delete only if the class created the <free_list_>
+
private:
+
ACE_Time_Value timeout_;
// Returned by <calculate_timeout>.
diff --git a/ace/Timer_Queue_T.i b/ace/Timer_Queue_T.i
index 752ae8c7d38..ad8ea45cdea 100644
--- a/ace/Timer_Queue_T.i
+++ b/ace/Timer_Queue_T.i
@@ -1,7 +1,122 @@
/* -*- C++ -*- */
-// $Id$
-// Timer_Queue_T.i
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set (const TYPE &type,
+ const void *a,
+ const ACE_Time_Value &t,
+ const ACE_Time_Value &i,
+ ACE_Timer_Node_T<TYPE> *n,
+ long timer_id)
+{
+ this->type_ = type;
+ this->act_ = a;
+ this->timer_value_ = t;
+ this->interval_ = i;
+ this->next_ = n;
+ this->timer_id_ = timer_id;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set (const TYPE &type,
+ const void *a,
+ const ACE_Time_Value &t,
+ const ACE_Time_Value &i,
+ ACE_Timer_Node_T<TYPE> *p,
+ ACE_Timer_Node_T<TYPE> *n,
+ long timer_id)
+{
+ this->type_ = type;
+ this->act_ = a;
+ this->timer_value_ = t;
+ this->interval_ = i;
+ this->prev_ = p;
+ this->next_ = n;
+ this->timer_id_ = timer_id;
+}
+
+template <class TYPE> ACE_INLINE TYPE &
+ACE_Timer_Node_T<TYPE>::get_type (void)
+{
+ return this->type_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_type (TYPE &type)
+{
+ this->type_ = type;
+}
+
+template <class TYPE> ACE_INLINE const void *
+ACE_Timer_Node_T<TYPE>::get_act (void)
+{
+ return this->act_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_act (void *act)
+{
+ this->act_ = act;
+}
+
+template <class TYPE> ACE_INLINE ACE_Time_Value &
+ACE_Timer_Node_T<TYPE>::get_timer_value (void)
+{
+ return this->timer_value_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_timer_value (ACE_Time_Value timer_value)
+{
+ this->timer_value_ = timer_value;
+}
+
+template <class TYPE> ACE_INLINE ACE_Time_Value &
+ACE_Timer_Node_T<TYPE>::get_interval (void)
+{
+ return this->interval_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_interval (ACE_Time_Value interval)
+{
+ this->interval_ = interval;
+}
+
+template <class TYPE> ACE_INLINE ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Node_T<TYPE>::get_prev (void)
+{
+ return this->prev_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_prev (ACE_Timer_Node_T<TYPE> *prev)
+{
+ this->prev_ = prev;
+}
+
+template <class TYPE> ACE_INLINE ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Node_T<TYPE>::get_next (void)
+{
+ return this->next_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_next (ACE_Timer_Node_T<TYPE> *next)
+{
+ this->next_ = next;
+}
+
+template <class TYPE> ACE_INLINE long
+ACE_Timer_Node_T<TYPE>::get_timer_id (void)
+{
+ return this->timer_id_;
+}
+
+template <class TYPE> ACE_INLINE void
+ACE_Timer_Node_T<TYPE>::set_timer_id (long timer_id)
+{
+ this->timer_id_ = timer_id;
+}
template <class TYPE, class FUNCTOR, class LOCK> ACE_INLINE void
ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::timer_skew (const ACE_Time_Value &skew)
@@ -29,7 +144,7 @@ ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::upcall (TYPE &type,
const void *act,
const ACE_Time_Value &cur_time)
{
- this->upcall_functor_.timeout (*this, type, act, cur_time);
+ this->upcall_functor ().timeout (*this, type, act, cur_time);
}
@@ -37,18 +152,23 @@ template <class TYPE, class FUNCTOR, class LOCK> ACE_INLINE ACE_Time_Value
ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::gettimeofday (void)
{
// Invoke gettimeofday via pointer to function.
- return gettimeofday_ ();
+ return this->gettimeofday_ ();
}
template <class TYPE, class FUNCTOR, class LOCK> ACE_INLINE void
ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::gettimeofday (ACE_Time_Value (*gettimeofday)(void))
{
- gettimeofday_ = gettimeofday;
+ this->gettimeofday_ = gettimeofday;
+}
+
+template <class TYPE, class FUNCTOR, class LOCK> ACE_INLINE LOCK &
+ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::mutex (void)
+{
+ return this->mutex_;
}
template <class TYPE, class FUNCTOR, class LOCK> ACE_INLINE FUNCTOR &
ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK>::upcall_functor (void)
{
- return this->upcall_functor_;
+ return *this->upcall_functor_;
}
-
diff --git a/ace/Timer_Wheel.h b/ace/Timer_Wheel.h
index 8f988afe117..5bc61b9592c 100644
--- a/ace/Timer_Wheel.h
+++ b/ace/Timer_Wheel.h
@@ -22,12 +22,12 @@
// compatibility.
typedef ACE_Timer_Wheel_T<ACE_Event_Handler *,
- ACE_Event_Handler_Handle_Timeout_Upcall,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
ACE_SYNCH_RECURSIVE_MUTEX>
ACE_Timer_Wheel;
typedef ACE_Timer_Wheel_Iterator_T<ACE_Event_Handler *,
- ACE_Event_Handler_Handle_Timeout_Upcall,
+ ACE_Event_Handler_Handle_Timeout_Upcall<ACE_SYNCH_RECURSIVE_MUTEX>,
ACE_SYNCH_RECURSIVE_MUTEX>
ACE_Timer_Wheel_Iterator;
diff --git a/ace/Timer_Wheel_T.cpp b/ace/Timer_Wheel_T.cpp
index 99d597f18e7..ceb8e44bf7d 100644
--- a/ace/Timer_Wheel_T.cpp
+++ b/ace/Timer_Wheel_T.cpp
@@ -5,90 +5,156 @@
#include "ace/Timer_Wheel_T.h"
+
+// Constructor that takes in a <wheel>, a reference to the timer queue
+
template <class TYPE, class FUNCTOR, class LOCK>
ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Wheel_Iterator_T (ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK> &wheel)
: timer_wheel_ (wheel)
{
+ // Nothing
}
-template <class TYPE, class FUNCTOR, class LOCK> int
-ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, LOCK>::next (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *&node,
- const ACE_Time_Value &cur_time)
+
+// Positions the iterator at the first node in the timing wheel
+
+template <class TYPE, class FUNCTOR, class LOCK> void
+ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, LOCK>::first (void)
{
- if (this->timer_wheel_.wheel_[this->pos_]->next_ == this->timer_wheel_.wheel_[this->pos_]
- || this->timer_wheel_.wheel_[this->pos_]->next_->timer_value_ > this->time_)
+ for (this->pos_ = 0;
+ this->pos_ < this->timer_wheel_.wheel_size_;
+ this->pos_++)
{
- ACE_Time_Value et = this->timer_wheel_.earliest_time ();
+ // Skip over empty entries
+ if (this->timer_wheel_.wheel_[this->pos_]->get_next () !=
+ this->timer_wheel_.wheel_[this->pos_])
+ {
+ this->list_item_ = this->timer_wheel_.wheel_[this->pos_]->get_next ();
+ return;
+ }
+ }
+
+ // The queue is empty if we are here
+ this->list_item_ = NULL;
+}
- if (this->timer_wheel_.size_ == 0 || et > cur_time)
- return 0;
- this->pos_ = (et.usec () / this->timer_wheel_.resolution_)
- % this->timer_wheel_.wheel_size_;
- this->time_ = ACE_Time_Value (et.sec (),
- this->pos_ * this->timer_wheel_.resolution_);
+// Positions the iterator at the next node in list or goes to the next
+// list
+
+template <class TYPE, class FUNCTOR, class LOCK> void
+ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, LOCK>::next (void)
+{
+ if (this->isdone ())
+ return;
+
+ this->list_item_ = this->list_item_->get_next ();
+
+ // If there is no more in the current list, go to the next
+ if (this->list_item_ == this->timer_wheel_.wheel_[this->pos_])
+ {
+ for (this->pos_++; this->pos_ < this->timer_wheel_.wheel_size_; this->pos_++)
+ {
+ // Check for an empty entry
+ if (this->timer_wheel_.wheel_[this->pos_]->get_next () !=
+ this->timer_wheel_.wheel_[this->pos_])
+ {
+ this->list_item_ = this->timer_wheel_.wheel_[this->pos_]->get_next ();
+ return;
+ }
+ }
+
+ this->list_item_ = NULL;
}
+}
- // Remove the earliest item
- node = this->timer_wheel_.wheel_[this->pos_]->next_;
- node->prev_->next_ = node->next_;
- node->next_->prev_ = node->prev_;
- this->timer_wheel_.size_--;
- return 1;
+// Returns true when we are at the end (when list_item_ == 0)
+
+template <class TYPE, class FUNCTOR, class LOCK> int
+ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, LOCK>::isdone (void)
+{
+ return this->list_item_ == NULL;
}
-template <class TYPE, class FUNCTOR, class LOCK> void
-ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, LOCK>::reset (void)
+
+// Returns the node at the current position in the sequence
+
+template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, LOCK>::item (void)
{
- ACE_Time_Value et = this->timer_wheel_.earliest_time ();
+ if (this->isdone ())
+ return NULL;
- this->pos_ = (et.usec () / this->timer_wheel_.resolution_)
- % this->timer_wheel_.wheel_size_;
- this->time_ = ACE_Time_Value (et.sec (),
- this->pos_ * this->timer_wheel_.resolution_);
+ return this->list_item_;
}
-ACE_ALLOC_HOOK_DEFINE(ACE_Timer_Wheel_T)
- template <class TYPE, class FUNCTOR, class LOCK>
+// Constructor that sets up the timing wheel and also may preallocate some
+// nodes on the free list
+
+template <class TYPE, class FUNCTOR, class LOCK>
ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Wheel_T (size_t wheelsize,
size_t resolution,
size_t prealloc,
- FUNCTOR *upcall_functor)
- : INHERITED (upcall_functor),
+ FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
+ : INHERITED (upcall_functor, freelist),
wheel_size_ (wheelsize),
resolution_ (resolution),
- current_pos_ ((ACE_OS::gettimeofday ().usec () / resolution) % wheel_size_),
- current_time_ (ACE_OS::gettimeofday ()),
- size_ (0),
- iterator_ (*this),
- freelist_ (NULL)
+ earliest_pos_ (0),
+ iterator_ (*this)
{
ACE_TRACE ("ACE_Timer_Wheel_T::ACE_Timer_Wheel_T");
size_t i;
+ this->gettimeofday (ACE_High_Res_Timer::gettimeofday);
+
// Create the timing wheel
- ACE_NEW (this->wheel_, (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *[wheelsize]));
+ ACE_NEW (this->wheel_, (ACE_Timer_Node_T<TYPE> *[wheelsize]));
+
+ // Create the dummy nodes
for (i = 0; i < wheelsize; i++)
{
- // Create the dummy nodes
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *tempnode = this->alloc_node ();
- tempnode->next_ = tempnode->prev_ = tempnode;
+ ACE_Timer_Node_T<TYPE> *tempnode = this->alloc_node ();
+ tempnode->set_next (tempnode);
+ tempnode->set_prev (tempnode);
this->wheel_[i] = tempnode;
}
// Do the preallocation
- for (i = 0; i < prealloc; i++)
+ this->free_list_->resize (prealloc);
+}
+
+template <class TYPE, class FUNCTOR, class LOCK>
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::ACE_Timer_Wheel_T (FUNCTOR *upcall_functor,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
+ : INHERITED (upcall_functor, freelist),
+ wheel_size_ (ACE_DEFAULT_TIMER_WHEEL_SIZE),
+ resolution_ (ACE_DEFAULT_TIMER_WHEEL_RESOLUTION),
+ earliest_pos_ (0),
+ iterator_ (*this)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::ACE_Timer_Wheel_T");
+ size_t i;
+
+ this->gettimeofday (ACE_High_Res_Timer::gettimeofday);
+
+ // Create the timing wheel
+ ACE_NEW (this->wheel_, (ACE_Timer_Node_T<TYPE> *[this->wheel_size_]));
+
+ // Create the dummy nodes
+ for (i = 0; i < this->wheel_size_; i++)
{
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *temp;
- ACE_NEW (temp, (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>));
- temp->next_ = this->freelist_;
- this->freelist_ = temp;
+ ACE_Timer_Node_T<TYPE> *tempnode = this->alloc_node ();
+ tempnode->set_next (tempnode);
+ tempnode->set_prev (tempnode);
+ this->wheel_[i] = tempnode;
}
}
+// Destructor just cleans up its memory
template <class TYPE, class FUNCTOR, class LOCK>
ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::~ACE_Timer_Wheel_T (void)
@@ -98,65 +164,50 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::~ACE_Timer_Wheel_T (void)
for (size_t i = 0; i < this->wheel_size_; i++)
{
// delete nodes until only the dummy node is left
- while (this->wheel_[i]->next_ != this->wheel_[i])
+ while (this->wheel_[i]->get_next () != this->wheel_[i])
{
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *next = this->wheel_[i]->next_;
- this->wheel_[i]->next_ = next->next_;
- next->next_->prev_ = this->wheel_[i];
- this->free_node (next);
+ ACE_Timer_Node_T<TYPE> *next = this->wheel_[i]->get_next ();
+ this->wheel_[i]->set_next (next->get_next ());
+ next->get_next ()->set_prev (this->wheel_[i]);
+ this->upcall_functor ().deletion (*this, next->get_type (), next->get_act ());
+ this->free_node (next);
}
// and now delete the dummy node
delete this->wheel_[i];
}
- // Get rid of the freelist now
- while (this->freelist_ != NULL)
- {
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *temp = this->freelist_;
- this->freelist_ = temp->next_;
- delete temp;
- }
-
+ // finally delete the wheel
delete [] this->wheel_;
}
+
+// Checks to see if <earliest_pos> points to a empty list (then it is empty)
+
template <class TYPE, class FUNCTOR, class LOCK> int
ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::is_empty (void) const
{
ACE_TRACE ("ACE_Timer_Wheel_T::is_empty");
- // Just check the size
- return this->size_ == 0;
+ return this->wheel_[this->earliest_pos_]->get_next () == this->wheel_[this->earliest_pos_];
}
+
+// Returns the first (earliest) node in the <wheel_>'s <earliest_pos_> list
+
template <class TYPE, class FUNCTOR, class LOCK> const ACE_Time_Value &
ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::earliest_time (void) const
{
ACE_TRACE ("ACE_Timer_Wheel_T::earliest_time");
- ACE_Time_Value earliest_time;
- size_t earliest_pos = 0;
-
- // Check every entry in the table
- for (size_t i = 0; i < this->wheel_size_; i++)
- {
- // Check for an empty entry
- if (this->wheel_[i]->next_ != this->wheel_[i])
- {
- // if initialization or if the time is earlier
- if (earliest_time == ACE_Time_Value::zero
- || this->wheel_[i]->timer_value_ < earliest_time)
- {
- earliest_time = this->wheel_[i]->next_->timer_value_;
- earliest_pos = i;
- }
- }
- }
-
- return this->wheel_[earliest_pos]->next_->timer_value_;
+ if (this->is_empty ())
+ return ACE_Time_Value::zero;
+ else
+ return this->wheel_[this->earliest_pos_]->get_next ()->get_timer_value ();
}
+// Create the node and pass it to reschedule. Also check to see if the
+// <earliest_pos> should be changed.
template <class TYPE, class FUNCTOR, class LOCK> long
ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::schedule (const TYPE &type,
@@ -167,30 +218,36 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::schedule (const TYPE &type,
ACE_TRACE ("ACE_Timer_Wheel_T::schedule");
ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, this->mutex_, -1));
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *tempnode = this->alloc_node ();
+ ACE_Timer_Node_T<TYPE> *tempnode = this->alloc_node ();
if (tempnode)
{
// Note that the timer_id is actually the pointer to the node
- // Use operator placement new.
- new (tempnode) ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> (type,
- act,
- delay,
- interval,
- NULL,
- NULL,
- (long) tempnode);
-
+ // Set the details of the node
+ tempnode->set (type,
+ act,
+ delay,
+ interval,
+ NULL,
+ NULL,
+ (long) tempnode);
+
+ // Reschedule will insert it into the correct position
this->reschedule (tempnode);
- return tempnode->timer_id_;
+
+ return tempnode->get_timer_id ();
}
- // Failure return.
+ // Failure return
errno = ENOMEM;
return -1;
}
+
+// Goes through every list in the wheel and if it finds a node with <type>
+// then it removes the node and continues on looking for other nodes
+
template <class TYPE, class FUNCTOR, class LOCK> int
ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::cancel (const TYPE &type,
int dont_call_handle_close)
@@ -200,38 +257,66 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::cancel (const TYPE &type,
int number_of_cancellations = 0;
+ // Walk through the wheel
for (size_t i = 0; i < this->wheel_size_; i++)
{
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *curr = this->wheel_[i]->next_;
+ ACE_Timer_Node_T<TYPE> *curr = this->wheel_[i]->get_next ();
+ // Walk through the list
while (curr != this->wheel_[i])
{
- if (curr->type_ == type)
+ if (curr->get_type () == type)
{
+ // Cancel it and remove it.
number_of_cancellations++;
if (dont_call_handle_close == 0
&& number_of_cancellations == 1)
- this->upcall_functor_.cancellation (*this, curr->type_);
+ this->upcall_functor ().cancellation (*this, curr->get_type ());
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *tempnode = curr;
- curr->prev_->next_ = curr->next_;
- curr->next_->prev_ = curr->prev_;
- curr = curr->next_;
-
- this->free_node (tempnode);
+ // Detach it from the list
+ ACE_Timer_Node_T<TYPE> *tempnode = curr;
+ curr->get_prev ()->set_next (curr->get_next ());
+ curr->get_next ()->set_prev (curr->get_prev ());
+
+ // Go on to the next and delete the detached node
+ curr = curr->get_next ();
+ this->free_node (tempnode);
}
else
{
- curr = curr->next_;
+ curr = curr->get_next ();
}
}
}
- this->size_ -= number_of_cancellations;
+ // Look for a new earliest time
+
+ ACE_Time_Value earliest_time; // defaults to zero
+
+ // Check every entry in the table
+ for (i = 0; i < this->wheel_size_; i++)
+ {
+ // Skip empty entries
+ if (this->wheel_[i]->get_next () != this->wheel_[i])
+ {
+ // if initialization or if the time is earlier
+ if (earliest_time == ACE_Time_Value::zero
+ || this->wheel_[i]->get_timer_value () < earliest_time)
+ {
+ earliest_time = this->wheel_[i]->get_next ()->get_timer_value ();
+ this->earliest_pos_ = i;
+ }
+ }
+ }
+
return number_of_cancellations;
}
+
+// Takes the <timer_id> and casts it to a pointer. Then it removes it
+// from its neighbors
+
template <class TYPE, class FUNCTOR, class LOCK> int
ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::cancel (long timer_id,
const void **act,
@@ -240,30 +325,62 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::cancel (long timer_id,
ACE_TRACE ("ACE_Timer_Wheel_T::cancel");
ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, this->mutex_, -1));
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *node = (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *) timer_id;
+ // Make sure we are getting a valid <timer_id>, not an error
+ // returned by schedule ()
+ if (timer_id == -1)
+ return 0;
- ACE_ASSERT (timer_id == node->timer_id_);
-
- // Check to see if the node looks like a true ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>
- if (timer_id == node->timer_id_)
+ ACE_Timer_Node_T<TYPE> *node = (ACE_Timer_Node_T<TYPE> *) timer_id;
+
+ // Check to see if the node looks like a true ACE_Timer_Node_T<TYPE>
+ if (timer_id == node->get_timer_id ())
{
- node->next_->prev_ = node->prev_;
- node->prev_->next_ = node->next_;
+ node->get_next ()->set_prev (node->get_prev ());
+ node->get_prev ()->set_next (node->get_next ());
if (act != 0)
- *act = node->act_;
+ *act = node->get_act ();
if (dont_call_handle_close == 0)
- this->upcall_functor_.cancellation (*this, node->type_);
+ this->upcall_functor ().cancellation (*this, node->get_type ());
+
+ // Find out what position it is in
+ size_t pos = (node->get_timer_value ().usec () / this->resolution_) % this->wheel_size_;
this->free_node (node);
- this->size_--;
+
+ // Get the new earliest time if we have to
+
+ if (pos == this->earliest_pos_)
+ {
+ ACE_Time_Value earliest_time; // defaults to zero
+
+ // Check every entry in the table
+ for (size_t i = 0; i < this->wheel_size_; i++)
+ {
+ // Skip empty entries
+ if (this->wheel_[i]->get_next () != this->wheel_[i])
+ {
+ // if initialization or if the time is earlier
+ if (earliest_time == ACE_Time_Value::zero
+ || this->wheel_[i]->get_timer_value () < earliest_time)
+ {
+ earliest_time = this->wheel_[i]->get_next ()->get_timer_value ();
+ this->earliest_pos_ = i;
+ }
+ }
+ }
+ }
+
return 1;
}
// Didn't find it if we are here
return 0;
}
+
+
+// Dumps out some properties of this object
template <class TYPE, class FUNCTOR, class LOCK> void
ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::dump (void) const
@@ -273,119 +390,195 @@ ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::dump (void) const
ACE_DEBUG ((LM_DEBUG, "\nwheel_size_ = %d", this->wheel_size_));
ACE_DEBUG ((LM_DEBUG, "\nresolution_ = %d", this->resolution_));
- ACE_DEBUG ((LM_DEBUG, "\ncurrent_pos_ = %d", this->current_pos_));
- ACE_DEBUG ((LM_DEBUG, "\nsize_ = %d", this->size_));
ACE_DEBUG ((LM_DEBUG, "\nwheel_ = \n"));
for (size_t i = 0; i < this->wheel_size_; i++)
{
ACE_DEBUG ((LM_DEBUG, "%d\n", i));
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *temp = this->wheel_[i]->next_;
+ ACE_Timer_Node_T<TYPE> *temp = this->wheel_[i]->get_next ();
while (temp != this->wheel_[i])
{
temp->dump ();
- temp = temp->next_;
+ temp = temp->get_next ();
}
}
ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
}
-template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *
-ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::alloc_node (void)
-{
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *temp;
- if (this->freelist_ == NULL)
- {
- ACE_NEW_RETURN (temp,
- (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>),
- 0);
- }
- else
- {
- temp = this->freelist_;
- this->freelist_ = temp->next_;
- }
-
- return temp;
-}
+// Removes the earliest node and then find the new <earliest_pos_>
-template <class TYPE, class FUNCTOR, class LOCK> void
-ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::free_node (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *node)
+template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T<TYPE> *
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::remove_first (void)
{
- // Add to the beginning of the freelist
- node->next_ = this->freelist_;
- this->freelist_ = node;
+ ACE_TRACE ("ACE_Timer_Wheel_T::remove_first");
- // Change the timer id so a cancel on this would not try to
- // delete it
- node->timer_id_ = 0;
-}
-
-template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *
-ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::remove (void)
-{
- ACE_TRACE ("ACE_Timer_Wheel_T::remove");
+ // Remove the item
+ ACE_Timer_Node_T<TYPE> *temp = this->wheel_[this->earliest_pos_]->get_next ();
+ temp->get_prev ()->set_next (temp->get_next ());
+ temp->get_next ()->set_prev (temp->get_prev ());
ACE_Time_Value earliest_time;
- size_t earliest_pos = 0;
-
- // Check every entry in the table
+
+ // Check every entry in the table for the new earliest item
for (size_t i = 0; i < this->wheel_size_; i++)
{
// Check for an empty entry
- if (this->wheel_[i]->next_ != this->wheel_[i])
+ if (this->wheel_[i]->get_next () != this->wheel_[i])
{
// if initialization or if the time is earlier
if (earliest_time == ACE_Time_Value::zero
- || this->wheel_[i]->timer_value_ < earliest_time)
+ || this->wheel_[i]->get_timer_value () < earliest_time)
{
- earliest_time = this->wheel_[i]->next_->timer_value_;
- earliest_pos = i;
+ earliest_time = this->wheel_[i]->get_next ()->get_timer_value ();
+ this->earliest_pos_ = i;
}
}
}
- // Remove and return
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *temp = this->wheel_[earliest_pos]->next_;
- temp->prev_->next_ = temp->next_;
- temp->next_->prev_ = temp->prev_;
-
- this->size_--;
return temp;
}
+
+// Takes an ACE_Timer_Node and inserts it into the correct position in the correct
+// list
+
template <class TYPE, class FUNCTOR, class LOCK> void
-ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::reschedule (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *expired)
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::reschedule (ACE_Timer_Node_T<TYPE> *expired)
{
ACE_TRACE ("ACE_Timer_Wheel_T::reschedule");
- size_t pos = (expired->timer_value_.usec () / this->resolution_) % this->wheel_size_;
+ size_t pos = (expired->get_timer_value ().usec () / this->resolution_) % this->wheel_size_;
+
+ // See if we need to update the earliest time
+ if (this->earliest_time () == ACE_Time_Value::zero
+ || this->earliest_time () < expired->get_timer_value ())
+ this->earliest_pos_ = pos;
// Insert time into dummy node
- this->wheel_[pos]->timer_value_ = expired->timer_value_;
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *cursor = this->wheel_[pos]->next_;
+ this->wheel_[pos]->set_timer_value (expired->get_timer_value ());
+ ACE_Timer_Node_T<TYPE> *cursor = this->wheel_[pos]->get_next ();
// Find position to insert
- while (cursor->timer_value_ < expired->timer_value_)
- cursor = cursor->next_;
+ while (cursor->get_timer_value () < expired->get_timer_value ())
+ cursor = cursor->get_next ();
// Insert
- expired->prev_ = cursor->prev_;
- expired->next_ = cursor;
- cursor->prev_ = expired;
- expired->prev_->next_ = expired;
-
- this->size_++;
+ expired->set_prev (cursor->get_prev ());
+ expired->set_next (cursor);
+ cursor->set_prev (expired);
+ expired->get_prev ()->set_next (expired);
}
+
+// Just return the iterator
+
template <class TYPE, class FUNCTOR, class LOCK> ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK> &
ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::iter (void)
{
- this->iterator_.reset ();
return this->iterator_;
}
+
+// Specialized expire which expires in total order. It is optimized by keeping
+// track of the list with the earliest element and the next earliest list. It
+// then goes through the earliest list until it can switch to the second list.
+// it keeps going until it finishes with everything before the <cur_time>
+
+template <class TYPE, class FUNCTOR, class LOCK> int
+ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK>::expire (const ACE_Time_Value &cur_time)
+{
+ ACE_TRACE ("ACE_Timer_Wheel_T::expire");
+ ACE_MT (ACE_GUARD_RETURN (LOCK, ace_mon, this->mutex_, -1));
+
+ int number_of_timers_expired = 0;
+ size_t i;
+ size_t earliest = this->wheel_size_;
+ ACE_Time_Value earliest_time = cur_time;
+ size_t next_earliest = this->wheel_size_;
+ ACE_Time_Value next_earliest_time;
+
+ // Find the earliest time
+ for (i = 0; i < this->wheel_size_; i++)
+ {
+ if (this->wheel_[i]->get_next () != this->wheel_[i]
+ && this->wheel_[i]->get_next ()->get_timer_value () < earliest_time)
+ {
+ earliest = i;
+ earliest_time = this->wheel_[i]->get_next ()->get_timer_value ();
+ }
+ }
+
+ // Check to see if there is anything to expire
+ if (this->wheel_[earliest]->get_next ()->get_timer_value () > cur_time)
+ return 0;
+
+ do
+ {
+ next_earliest_time = cur_time;
+
+ // Find 2nd earliest position
+ for (i = 0; i < this->wheel_size_; i++)
+ {
+ if (i != earliest
+ && this->wheel_[i]->get_next () != this->wheel_[i]
+ && this->wheel_[i]->get_next ()->get_timer_value () < next_earliest_time)
+ {
+ next_earliest = i;
+ next_earliest_time = this->wheel_[i]->get_next ()->get_timer_value ();
+ }
+ }
+
+ while (this->wheel_[earliest]->get_next ()->get_timer_value () < next_earliest_time)
+ {
+ // Remove the first node in the earliest position
+ ACE_Timer_Node_T<TYPE> *expired = this->wheel_[earliest]->get_next ();
+ this->wheel_[earliest]->set_next (expired->get_next ());
+ expired->get_next ()->set_prev (this->wheel_[earliest]);
+
+ TYPE &type = expired->get_type ();
+ const void *act = expired->get_act ();
+ int reclaim = 1;
+
+ // 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);
+ reclaim = 0;
+ }
+
+ // call the functor
+ this->upcall (type, act, cur_time);
+
+ if (reclaim)
+ // Free up the node and the token
+ this->free_node (expired);
+
+ ++number_of_timers_expired;
+
+ // Check to see if we are empty
+ if (this->wheel_[earliest]->get_next () == this->wheel_[earliest])
+ break;
+ }
+
+ if (next_earliest_time == cur_time)
+ break;
+
+ earliest = next_earliest;
+ } while (next_earliest != this->wheel_size_);
+
+ return number_of_timers_expired;
+}
+
+
#endif /* ACE_TIMER_WHEEL_T_C */
diff --git a/ace/Timer_Wheel_T.h b/ace/Timer_Wheel_T.h
index 28a2a089d3b..213d6a9c3c8 100644
--- a/ace/Timer_Wheel_T.h
+++ b/ace/Timer_Wheel_T.h
@@ -28,30 +28,35 @@ class ACE_Timer_Wheel_Iterator_T : public ACE_Timer_Queue_Iterator_T <TYPE, FUNC
// Iterates over an <ACE_Timer_Wheel>.
//
// = DESCRIPTION
- // This is a special type of iterator that "advances" by moving
- // the head of the timer queue up by one every time.
+ // This is a generic iterator that can be used to visit every
+ // node of a timer queue. Be aware that it doesn't transverse
+ // in the order of timeout values.
{
public:
ACE_Timer_Wheel_Iterator_T (ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK> &);
- // Constructor.
+ // Constructor
- virtual int next (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *&timer_node,
- const ACE_Time_Value &cur_time);
- // Pass back the next <timer_node> that hasn't been seen yet, if its
- // <time_value_> <= <cur_time>. In addition, moves the timer queue
- // forward by one node. Returns 0 when all <timer_nodes> have been
- // seen, else 1.
+ virtual void first (void);
+ // Positions the iterator at the earliest node in the Timer Queue
- void reset (void);
- // Resets the iterator
+ virtual void next (void);
+ // Positions the iterator at the next node in the Timer Queue
+
+ virtual int isdone (void);
+ // Returns true when there are no more nodes in the sequence
+
+ virtual ACE_Timer_Node_T<TYPE> *item (void);
+ // Returns the node at the current position in the sequence
protected:
ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK> &timer_wheel_;
// Pointer to the <ACE_Timer_List> that we are iterating over.
-private:
- size_t pos_; // Current position in the timing wheel
- ACE_Time_Value time_; // Corresponding time of <pos_>
+ size_t pos_;
+ // Current position in the timing wheel
+
+ ACE_Timer_Node_T<TYPE> *list_item_;
+ // Pointer to the position in the the <pos_>th list
};
template <class TYPE, class FUNCTOR, class LOCK>
@@ -76,19 +81,34 @@ public:
// Type of iterator
friend class ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, LOCK>;
- // Iterator is a friend.
+ // Iterator is a friend
typedef ACE_Timer_Queue_T<TYPE, FUNCTOR, LOCK> INHERITED;
- // Type inherited from.
+ // Type inherited from
- // = Initialization and termination methods.
- ACE_Timer_Wheel_T (size_t wheelsize = ACE_DEFAULT_TIMER_WHEEL_SIZE,
- size_t resolution = ACE_DEFAULT_TIMER_WHEEL_RESOLUTION,
+ // = Initialization and termination methods
+
+ ACE_Timer_Wheel_T (size_t wheelsize,
+ size_t resolution,
size_t prealloc = 0,
- FUNCTOR *upcall_functor = 0);
- // Constructor that takes in a size for the timing wheel and a
- // resolution for placement in the timing wheel lists (in
- // microseconds).
+ FUNCTOR *upcall_functor = 0,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
+ // Constructor that takes in <wheelsize> - size of the timing wheel,
+ // <resolution> - resolution of time values the hashing function uses,
+ // and <upcall_functor> - a functor that will be used instead of creating
+ // a default functor. Also, when the freelist is created, <prealloc> nodes
+ // will be allocated. This can also take in a upcall functor and freelist
+ // (if 0, then defaults will be created)
+
+ ACE_Timer_Wheel_T (FUNCTOR *upcall_functor = 0,
+ ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist = 0);
+ // Default constructor. <upcall_functor> is the instance of the
+ // FUNCTOR to be used by the queue. If <upcall_functor> is 0, Timer
+ // Queue will create a default FUNCTOR. <freelist> the freelist of
+ // timer nodes. If 0, then a default freelist will be created. The
+ // defaults will be used for size and resolution and no preallocation
+ // (ACE_DEFAULT_TIMER_WHEEL_SIZE, ACE_DEFAULT_TIMER_WHEEL_RESOLUTION)
+
virtual ~ACE_Timer_Wheel_T (void);
// Destructor
@@ -107,14 +127,9 @@ public:
// If it expires then <act> is passed in as the value to the
// <functor>. If <interval> is != to <ACE_Time_Value::zero> then it
// is used to reschedule the <type> automatically. This method
- // returns a <timer_id> that uniquely identifies the the <type>
- // entry in an internal list. This <timer_id> can be used to cancel
- // the timer before it expires. The cancellation ensures that
- // <timer_ids> are unique up to values of greater than 2 billion
- // timers. As long as timers don't stay around longer than this
- // there should be no problems with accidentally deleting the wrong
- // timer. Returns -1 on failure (which is guaranteed never to be a
- // valid <timer_id>).
+ // returns a <timer_id> that uniquely identifies the the timer.
+ // This <timer_id> can be used to cancel the timer before it expires.
+ // Returns -1 on failure.
virtual int cancel (const TYPE &type,
int dont_call_handle_close = 1);
@@ -133,28 +148,25 @@ public:
// 0 then the <functor> will be invoked. Returns 1 if cancellation
// succeeded and 0 if the <timer_id> wasn't found.
- virtual void dump (void) const;
- // Dump the state of an object.
+ virtual int expire (const ACE_Time_Value &current_time);
+ // Run the <functor> for all timers whose values are <= <cur_time>.
+ // This does not account for <timer_skew>. Returns the number of
+ // timers canceled.
-protected:
- virtual ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *alloc_node (void);
- // Factory method that allocates a new node (uses operator new).
+ virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK> &iter (void);
+ // Returns a pointer to this <ACE_Timer_Queue_T>'s iterator.
- virtual void free_node (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *);
- // Factory method that frees a previously allocated node (uses
- // operator delete).
+ virtual ACE_Timer_Node_T<TYPE> *remove_first (void);
+ // Removes the earliest node from the queue and returns it
-private:
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *remove (void);
- // Removes the earliest node and returns a pointer to it.
+ virtual void dump (void) const;
+ // Dump the state of an object.
- virtual void reschedule (ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *);
+private:
+ virtual void reschedule (ACE_Timer_Node_T<TYPE> *);
// Reschedule an "interval" node
- virtual ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, LOCK> &iter (void);
- // Returns a pointer to this <ACE_Timer_Queue_T>'s iterator.
-
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> **wheel_;
+ ACE_Timer_Node_T<TYPE> **wheel_;
// Timing Wheel.
size_t wheel_size_;
@@ -163,11 +175,8 @@ private:
size_t resolution_;
// Resolution (in microsoconds) of the timing wheel.
- size_t current_pos_;
- // Current position in the timing wheel.
-
- ACE_Time_Value current_time_;
- // Keeps track of the previous time <current_pos_> was updated.
+ size_t earliest_pos_;
+ // Index of the list with the earliest time
long size_;
// Keeps track of the size of the queue
@@ -175,8 +184,8 @@ private:
ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, LOCK> iterator_;
// Iterator used to expire timers.
- ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK> *freelist_;
- // Pointer to the freelist of <ACE_Timer_Node_T<TYPE, FUNCTOR, LOCK>>.
+ ACE_Timer_Node_T<TYPE> *freelist_;
+ // Pointer to the freelist of <ACE_Timer_Node_T<TYPE>>.
// = Don't allow these operations for now.
ACE_Timer_Wheel_T (const ACE_Timer_Wheel_T<TYPE, FUNCTOR, LOCK> &);
diff --git a/tests/Timer_Queue_Test.cpp b/tests/Timer_Queue_Test.cpp
index 3bb96018147..0d5cf9abf3e 100644
--- a/tests/Timer_Queue_Test.cpp
+++ b/tests/Timer_Queue_Test.cpp
@@ -1,5 +1,3 @@
-// $Id$
-
// ============================================================================
//
// = LIBRARY
@@ -9,13 +7,13 @@
// Timer_Queue_Test.cpp
//
// = DESCRIPTION
-// This is a simple test of <ACE_Timer_Queue> and two of its
-// subclasses (<ACE_Timer_List> and <ACE_Timer_Heap>). The test
-// sets up a bunch of timers and then adds them to a timer
-// queue. The functionality of the timer queue is then tested. No
-// command line arguments are needed to run the test.
+// This is a simple test of <ACE_Timer_Queue> and four of its
+// subclasses (<ACE_Timer_List>, <ACE_Timer_Heap>, <ACE_Timer_Wheel>, and
+// <ACE_Timer_Hash>). The test sets up a bunch of timers and then adds
+// them to a timer queue. The functionality of the timer queue is then
+// tested. No command line arguments are needed to run the test.
//
-// = AUTHOR
+// = AUTHORS
// Douglas C. Schmidt, Prashant Jain, and Darrell Brunsch
//
// ============================================================================
@@ -24,21 +22,20 @@
#include "ace/Timer_List.h"
#include "ace/Timer_Heap.h"
#include "ace/Timer_Wheel.h"
+#include "ace/Timer_Hash.h"
#include "test_config.h"
-static void
-randomize_array (long array[], size_t size)
+template <class T> static void
+randomize_array (T array[], size_t size)
{
size_t i;
- ACE_OS::srand (ACE_OS::time (0L));
-
// Randomize the array.
for (i = 0; i < size; i++)
{
int index = ACE_OS::rand() % size--;
- long temp = array [index];
+ T temp = array [index];
array [index] = array [size];
array [size] = temp;
}
@@ -86,13 +83,16 @@ test_functionality (ACE_Timer_Queue *tq)
long timer_id;
timer_id = tq->schedule (&eh, (const void *) 1,
- ACE_OS::gettimeofday ());
+ tq->gettimeofday ());
ACE_ASSERT (timer_id != -1);
+ ACE_ASSERT (tq->is_empty () == 0); //==
ACE_ASSERT (tq->schedule (&eh, (const void *) 42,
- ACE_OS::gettimeofday ()) != -1);
+ tq->gettimeofday ()) != -1);
+ ACE_ASSERT (tq->is_empty () == 0); //==
ACE_ASSERT (tq->schedule (&eh, (const void *) 42,
- ACE_OS::gettimeofday ()) != -1);
+ tq->gettimeofday ()) != -1);
+ ACE_ASSERT (tq->is_empty () == 0); //==
// The following method will trigger a call to <handle_close>.
ACE_ASSERT (tq->cancel (timer_id, 0, 0) == 1);
ACE_ASSERT (tq->is_empty () == 0);
@@ -100,23 +100,23 @@ test_functionality (ACE_Timer_Queue *tq)
ACE_ASSERT (tq->expire () == 2);
ACE_ASSERT (tq->schedule (&eh, (const void *) 4,
- ACE_OS::gettimeofday ()) != -1);
+ tq->gettimeofday ()) != -1);
ACE_ASSERT (tq->schedule (&eh, (const void *) 5,
- ACE_OS::gettimeofday ()) != -1);
-
+ tq->gettimeofday ()) != -1);
+
// The following method will trigger a call to <handle_close>.
ACE_ASSERT (tq->cancel (&eh, 0) == 2);
ACE_ASSERT (tq->is_empty ());
ACE_ASSERT (tq->expire () == 0);
ACE_ASSERT (tq->schedule (&eh, (const void *) 007,
- ACE_OS::gettimeofday ()) != -1);
+ tq->gettimeofday ()) != -1);
ACE_ASSERT (tq->expire () == 1);
timer_id = tq->schedule (&eh, (const void *) 6,
- ACE_OS::gettimeofday ());
+ tq->gettimeofday ());
ACE_ASSERT (timer_id != -1);
ACE_ASSERT (tq->schedule (&eh, (const void *) 7,
- ACE_OS::gettimeofday ()) != -1);
+ tq->gettimeofday ()) != -1);
// The following method will *not* trigger a call to <handle_close>.
ACE_ASSERT (tq->cancel (timer_id) == 1);
@@ -138,13 +138,19 @@ test_performance (ACE_Timer_Queue *tq,
// Test the amount of time required to schedule all the timers.
+ ACE_Time_Value *times;
+ ACE_NEW (times, ACE_Time_Value[max_iterations]);
+
+ for (i = 0; i < max_iterations; i++)
+ times[i] = tq->gettimeofday ();
+
timer.start ();
for (i = 0; i < max_iterations; i++)
{
timer_ids[i] = tq->schedule (&eh,
(const void *) 42,
- ACE_OS::gettimeofday ());
+ times[i]);
ACE_ASSERT (timer_ids[i] != -1);
}
@@ -166,9 +172,7 @@ test_performance (ACE_Timer_Queue *tq,
"time per call = %f usecs\n",
(et.user_time / double (max_iterations)) * 1000000));
- // Test the amount of time required to cancel all the timers. We
- // start from the "back" in order to measure the worst case
- // performance for the <ACE_Timer_List> (which uses linear search).
+ // Test the amount of time required to cancel all the timers.
timer.start ();
@@ -199,7 +203,7 @@ test_performance (ACE_Timer_Queue *tq,
for (i = 0; i < max_iterations; i++)
ACE_ASSERT (tq->schedule (&eh,
(const void *) 42,
- ACE_OS::gettimeofday ()) != -1);
+ tq->gettimeofday ()) != -1);
ACE_ASSERT (tq->is_empty () == 0);
@@ -215,25 +219,24 @@ test_performance (ACE_Timer_Queue *tq,
max_iterations, test_name));
ACE_DEBUG ((LM_DEBUG,
"real time = %f secs, user time = %f secs, system time = %f secs\n",
- et.real_time, et.user_time, et.system_time));
+ et.real_time, et.user_time, et.system_time));
ACE_DEBUG ((LM_DEBUG,
"time per call = %f usecs\n",
(et.user_time / double (max_iterations)) * 1000000));
- // Test the amount of time required to randomly expire all the
+ // Test the amount of time required to randomly cancel all the
// timers.
for (i = 0; i < max_iterations; i++)
{
- timer_ids[i] = tq->schedule (&eh, (const void *) 42,
- ACE_OS::gettimeofday ());
+ timer_ids[i] = tq->schedule (&eh,
+ (const void *) 42,
+ tq->gettimeofday ());
ACE_ASSERT (timer_ids[i] != -1);
}
ACE_ASSERT (tq->is_empty () == 0);
- randomize_array (timer_ids, max_iterations);
-
timer.start ();
for (i = max_iterations - 1; i >= 0; i--)
@@ -245,34 +248,95 @@ test_performance (ACE_Timer_Queue *tq,
timer.elapsed_time (et);
- ACE_DEBUG ((LM_DEBUG, "time to randomly expire %d timers for %s\n",
- max_iterations, test_name));
- ACE_DEBUG ((LM_DEBUG, "real time = %f secs, user time = %f secs, system time = %f secs\n",
- et.real_time, et.user_time, et.system_time));
- ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n",
- (et.user_time / double (max_iterations)) * 1000000));
+ ACE_DEBUG ((LM_DEBUG,
+ "time to randomly cancel %d timers for %s\n",
+ max_iterations, test_name));
+ ACE_DEBUG ((LM_DEBUG,
+ "real time = %f secs, user time = %f secs, system time = %f secs\n",
+ et.real_time, et.user_time, et.system_time));
+ ACE_DEBUG ((LM_DEBUG,
+ "time per call = %f usecs\n",
+ (et.user_time / double (max_iterations)) * 1000000));
+
+ // Test the amount of time required to randomly schedule all the timers.
+
+ ACE_Time_Value now = tq->gettimeofday ();
+
+ for (i = 0; i < max_iterations; i++)
+ times[i] = now + ACE_Time_Value (0, ACE_OS::rand () % 1000000);
+
+ timer.start ();
+
+ for (i = 0; i < max_iterations; i++)
+ {
+ timer_ids[i] = tq->schedule (&eh,
+ (const void *) 42,
+ times[i]);
+ ACE_ASSERT (timer_ids[i] != -1);
+ }
+
+ ACE_ASSERT (tq->is_empty () == 0);
+
+ timer.stop ();
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "time to randomly schedule %d timers for %s\n",
+ max_iterations, test_name));
+ ACE_DEBUG ((LM_DEBUG,
+ "real time = %f secs, user time = %f secs, system time = %f secs\n",
+ et.real_time, et.user_time, et.system_time));
+ ACE_DEBUG ((LM_DEBUG,
+ "time per call = %f usecs\n",
+ (et.user_time / double (max_iterations)) * 1000000));
+
+ // Test the amount of time required to cancel all the timers.
+
+ // Make sure everything is ready to be expired
+
+ while (tq->gettimeofday () < now + ACE_Time_Value (1))
+ continue;
+
+ timer.start ();
+
+ tq->expire ();
+
+ ACE_ASSERT (tq->is_empty ());
+
+ timer.stop ();
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "time to expire %d randomly scheduled timers for %s\n",
+ max_iterations, test_name));
+ ACE_DEBUG ((LM_DEBUG,
+ "real time = %f secs, user time = %f secs, system time = %f secs\n",
+ et.real_time, et.user_time, et.system_time));
+ ACE_DEBUG ((LM_DEBUG,
+ "time per call = %f usecs\n",
+ (et.user_time / double (max_iterations)) * 1000000));
+
+ delete times;
}
-struct Timer_Queues
+struct Timer_Queue_List
{
+ Timer_Queue_List (ACE_Timer_Queue *queue, const char *name, Timer_Queue_List *next = NULL)
+ : queue_ (queue),
+ name_ (name),
+ next_ (next)
+ {}
+
ACE_Timer_Queue *queue_;
// Pointer to the subclass of <ACE_Timer_Queue> that we're testing.
const char *name_;
// Name of the Queue that we're testing.
-};
-
-// New Timer_Queue implementations should be added to the end of this
-// table.
-static Timer_Queues timer_queues[] =
-{
- { 0, "ACE_Timer_Heap (preallocated)" },
- { 0, "ACE_Timer_Heap (non-preallocated)" },
- { 0, "ACE_Timer_Wheel (preallocated)" },
- { 0, "ACE_Timer_Wheel (non-preallocated)" },
- { new ACE_Timer_List, "ACE_Timer_List" },
- { 0, 0 },
+ Timer_Queue_List *next_;
+ // Pointer to the next <Timer_Queues> structure
};
int
@@ -280,47 +344,104 @@ main (int argc, char *argv[])
{
ACE_START_TEST ("Timer_Queue_Test");
+ ACE_High_Res_Timer::get_env_global_scale_factor();
+
+ ACE_OS::srand (ACE_OS::time (0L));
+
if (argc > 1)
max_iterations = ACE_OS::atoi (argv[1]);
// = Perform initializations.
+
+ Timer_Queue_List *tq_list = NULL;
- // Preallocate memory.
- ACE_NEW_RETURN (timer_queues[0].queue_,
- ACE_Timer_Heap (ACE_DEFAULT_TIMERS, 1),
- -1);
+ // Add new Timer_Queue implementations here.
+
- // Don't preallocate memory.
- ACE_NEW_RETURN (timer_queues[1].queue_,
- ACE_Timer_Heap,
- -1);
+ // Timer_Hash (Heap)
- // Preallocate memory.
- ACE_NEW_RETURN (timer_queues[2].queue_,
- ACE_Timer_Wheel (ACE_DEFAULT_TIMER_WHEEL_SIZE,
- ACE_DEFAULT_TIMER_WHEEL_RESOLUTION,
- ACE_DEFAULT_TIMERS),
+ ACE_NEW_RETURN (tq_list,
+ Timer_Queue_List (new ACE_Timer_Hash_Heap,
+ "ACE_Timer_Hash (Heap)",
+ tq_list),
+ -1);
+
+ // Timer_Hash
+
+ ACE_NEW_RETURN (tq_list,
+ Timer_Queue_List (new ACE_Timer_Hash,
+ "ACE_Timer_Hash",
+ tq_list),
+ -1);
+
+ // Timer_List
+
+ ACE_NEW_RETURN (tq_list,
+ Timer_Queue_List (new ACE_Timer_List,
+ "ACE_Timer_List",
+ tq_list),
+ -1);
+
+ // Timer_Wheel without preallocated memory
+
+ ACE_NEW_RETURN (tq_list,
+ Timer_Queue_List (new ACE_Timer_Wheel,
+ "ACE_Timer_Wheel (non-preallocated)",
+ tq_list),
+ -1);
+
+ // Timer_Wheel with preallocated memory.
+
+ ACE_NEW_RETURN (tq_list,
+ Timer_Queue_List (new ACE_Timer_Wheel (ACE_DEFAULT_TIMER_WHEEL_SIZE,
+ ACE_DEFAULT_TIMER_WHEEL_RESOLUTION,
+ max_iterations),
+ "ACE_Timer_Wheel (preallocated)",
+ tq_list),
-1);
- // Don't preallocate memory.
- ACE_NEW_RETURN (timer_queues[3].queue_,
- ACE_Timer_Wheel,
- -1);
+
+
+ // Timer_Heap without preallocated memory.
+
+ ACE_NEW_RETURN (tq_list,
+ Timer_Queue_List (new ACE_Timer_Heap,
+ "ACE_Timer_Heap (non-preallocated)",
+ tq_list),
+ -1);
+
+ // Timer_Heap with preallocate memory.
+
+ ACE_NEW_RETURN (tq_list,
+ Timer_Queue_List (new ACE_Timer_Heap (max_iterations, 1),
+ "ACE_Timer_Heap (preallocated)",
+ tq_list),
+ -1);
+
+
+
+ // Create the Timer ID array
ACE_NEW_RETURN (timer_ids,
long[max_iterations],
-1);
+
+ Timer_Queue_List *tq_ptr = tq_list;
- for (int i = 0; timer_queues[i].name_ != 0; i++)
+ while (tq_ptr != NULL)
{
ACE_DEBUG ((LM_DEBUG, "**** starting test of %s\n",
- timer_queues[i].name_));
- test_functionality (timer_queues[i].queue_);
- test_performance (timer_queues[i].queue_,
- timer_queues[i].name_);
- delete timer_queues[i].queue_;
+ tq_ptr->name_));
+ test_functionality (tq_ptr->queue_);
+ test_performance (tq_ptr->queue_,
+ tq_ptr->name_);
+ delete tq_ptr->queue_;
+ Timer_Queue_List *temp = tq_ptr;
+ tq_ptr = tq_ptr->next_;
+ delete temp;
}
+
ACE_END_TEST;
return 0;
}