summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog-97a10
-rw-r--r--ace/Timer_Heap.cpp102
-rw-r--r--ace/Timer_Heap.h15
-rw-r--r--ace/Timer_List.cpp4
-rw-r--r--ace/Timer_List.h10
-rw-r--r--ace/Timer_Queue.cpp6
-rw-r--r--ace/Timer_Queue.h6
-rw-r--r--tests/Timer_Queue_Test.cpp14
8 files changed, 139 insertions, 28 deletions
diff --git a/ChangeLog-97a b/ChangeLog-97a
index 30a05df572f..50e460c369b 100644
--- a/ChangeLog-97a
+++ b/ChangeLog-97a
@@ -1,5 +1,15 @@
Mon Feb 10 15:27:02 1997 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu>
+ * ace/Timer_Queue: Added a virtual destructor so that subclasses
+ deleted via ACE_Timer_Queue *'s will call the right destructor.
+ Thanks to Stuart Powell <stuartp@in.ot.com.au> for reporting
+ this.
+
+ * ace/Timer_Heap.cpp: Added support for automatically growing
+ ACE_Timer_Heaps. This allows heaps to grow automatically as new
+ ACE_Event_Handlers are added dynamically. Thanks to Stuart
+ Powell <stuartp@in.ot.com.au> for this enhancement.
+
* ace/Memory_Pool: Added support that allows flags to be passed in
to the MMAP_Memory_Pool. This can be used to set the
appropriate type of backing store semantics (e.g., MAP_PRIVATE
diff --git a/ace/Timer_Heap.cpp b/ace/Timer_Heap.cpp
index 3a4fd301422..75bebd1c899 100644
--- a/ace/Timer_Heap.cpp
+++ b/ace/Timer_Heap.cpp
@@ -1,7 +1,3 @@
-// Timer_Heap.cpp
-// $Id$
-
-#define ACE_BUILD_DLL
#include "ace/Timer_Heap.h"
ACE_Timer_Heap_Iterator::ACE_Timer_Heap_Iterator (ACE_Timer_Heap &heap)
@@ -55,7 +51,11 @@ ACE_Timer_Heap::ACE_Timer_Heap (size_t size,
{
ACE_NEW (this->preallocated_nodes_,
ACE_Timer_Node[size]);
-
+
+ // Add allocated array to set of such arrays for deletion
+ // on cleanup.
+ this->preallocated_node_set_.insert (this->preallocated_nodes_);
+
// Form the freelist by linking the next_ pointers together.
for (size_t j = 1; j < size; j++)
this->preallocated_nodes_[j - 1].next_ =
@@ -75,7 +75,18 @@ ACE_Timer_Heap::~ACE_Timer_Heap (void)
ACE_TRACE ("ACE_Timer_Heap::~ACE_Timer_Heap");
delete [] this->heap_;
delete [] this->timer_ids_;
- delete [] this->preallocated_nodes_;
+
+ // clean up any preallocated timer nodes
+ if (preallocated_nodes_ != 0)
+ {
+ ACE_Unbounded_Set_Iterator<ACE_Timer_Node *>
+ set_iterator (this->preallocated_node_set_);
+
+ for (ACE_Timer_Node **entry = 0;
+ set_iterator.next (entry) !=0;
+ set_iterator.advance ())
+ delete [] *entry;
+ }
}
int
@@ -247,11 +258,82 @@ ACE_Timer_Heap::reheap_down (ACE_Timer_Node *moved_node,
void
ACE_Timer_Heap::insert (ACE_Timer_Node *new_node)
{
+ if (this->cur_size_ + 1 >= max_size_)
+ this->grow_heap ();
+
this->reheap_up (new_node);
this->cur_size_++;
}
void
+ACE_Timer_Heap::grow_heap (void)
+{
+ // all the containers will double in size from max_size_
+ size_t new_size = max_size_ * 2;
+
+ // First grow the heap itself.
+
+ ACE_Timer_Node **new_heap = 0;
+ ACE_NEW (new_heap, ACE_Timer_Node *[new_size]);
+ ACE_OS::memcpy (new_heap, this->heap_,
+ max_size_ * sizeof (ACE_Timer_Node *));
+ delete [] this->heap_;
+ this->heap_ = new_heap;
+
+ // Grow the array of timer ids.
+
+ int *new_timer_ids = 0;
+
+ ACE_NEW (new_timer_ids, int[new_size]);
+
+ ACE_OS::memcpy (new_timer_ids, this->timer_ids_, max_size_ * sizeof (int));
+
+ delete [] timer_ids_;
+ this->timer_ids_ = new_timer_ids;
+
+ // and add the new elements to the end of the "freelist"
+ for (size_t i = this->max_size_; i < new_size; i++)
+ this->timer_ids_[i] = -(i + 1);
+
+ // Grow the preallocation array (if using preallocation)
+ if (this->preallocated_nodes_ != 0)
+ {
+ // Create a new array with max_size elements to link in
+ // to existing list.
+ ACE_NEW (this->preallocated_nodes_,
+ ACE_Timer_Node[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];
+
+ // NULL-terminate the new list.
+ this->preallocated_nodes_[this->max_size_ - 1].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* previous = this->preallocated_nodes_freelist_;
+
+ for (ACE_Timer_Node* current = this->preallocated_nodes_freelist_->next_;
+ current != 0;
+ current = current->next_)
+ previous = current;
+
+ previous->next_ = &this->preallocated_nodes_[0];
+ }
+ }
+
+ this->max_size_ = new_size;
+}
+
+void
ACE_Timer_Heap::reheap_up (ACE_Timer_Node *new_node)
{
int parent;
@@ -310,6 +392,10 @@ ACE_Timer_Heap::alloc_node (void)
0);
else
{
+ // check to see if the heap needs to grow
+ if (this->preallocated_nodes_freelist_ == 0)
+ this->grow_heap ();
+
temp = this->preallocated_nodes_freelist_;
// Remove the element from the freelist.
@@ -414,9 +500,7 @@ ACE_Timer_Heap::cancel (ACE_Event_Handler *handler)
// Try to locate the ACE_Timer_Node that matches the timer_id.
- for (size_t i = 0;
- i < this->cur_size_;
- )
+ for (size_t i = 0; i < this->cur_size_; )
{
if (this->heap_[i]->handler_ == handler)
{
diff --git a/ace/Timer_Heap.h b/ace/Timer_Heap.h
index 963c4d28967..3dee9a4a8ee 100644
--- a/ace/Timer_Heap.h
+++ b/ace/Timer_Heap.h
@@ -18,6 +18,7 @@
#define ACE_TIMER_HEAP_H
#include "ace/Timer_Queue.h"
+#include "ace/Set.h"
// Forward declaration
class ACE_Timer_Heap;
@@ -47,7 +48,7 @@ protected:
};
class ACE_Export ACE_Timer_Heap : public ACE_Timer_Queue
- // = TITLE
+ // = TITLE
// Provides a very fast and predictable timer implementation.
//
// = DESCRIPTION
@@ -138,6 +139,11 @@ private:
void insert (ACE_Timer_Node *new_node);
// Insert <new_node> into the heap and restore the heap property.
+ void grow_heap (void);
+ // Doubles the size of the heap and the corresponding timer_ids array.
+ // If preallocation is used, will also double the size of the
+ // preallocated array of ACE_Timer_Nodes.
+
void reheap_up (ACE_Timer_Node *new_node);
// Restore the heap property.
@@ -188,11 +194,16 @@ private:
ACE_Timer_Node *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.
+ // costs. In auto-growing implementation, this points to the
+ // last array of nodes allocated.
ACE_Timer_Node *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 *> preallocated_node_set_;
+ // Set of pointers to the arrays of preallocated timer nodes.
+ // Used to delete the allocated memory when required.
};
#endif /* ACE_TIMER_HEAP_H */
diff --git a/ace/Timer_List.cpp b/ace/Timer_List.cpp
index b8965303618..67aff00b909 100644
--- a/ace/Timer_List.cpp
+++ b/ace/Timer_List.cpp
@@ -1,7 +1,3 @@
-// Timer_List.cpp
-// $Id$
-
-#define ACE_BUILD_DLL
#include "ace/Timer_List.h"
ACE_Timer_List_Iterator::ACE_Timer_List_Iterator (ACE_Timer_List &list)
diff --git a/ace/Timer_List.h b/ace/Timer_List.h
index fa25fdbafa0..34a47d0fd9b 100644
--- a/ace/Timer_List.h
+++ b/ace/Timer_List.h
@@ -35,7 +35,7 @@ public:
// Constructor.
virtual int next (ACE_Timer_Node *&timer_node,
- const ACE_Time_Value &cur_time);
+ 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
@@ -47,7 +47,7 @@ protected:
};
class ACE_Export ACE_Timer_List : public ACE_Timer_Queue
- // = TITLE
+ // = TITLE
// Provides a simple implementation of timers.
//
// = DESCRIPTION
@@ -81,9 +81,9 @@ public:
// Returns the time of the earlier node in the <ACE_Timer_List>.
virtual int schedule (ACE_Event_Handler *event_handler,
- const void *arg,
- const ACE_Time_Value &delay,
- const ACE_Time_Value &interval = ACE_Time_Value::zero);
+ const void *arg,
+ const ACE_Time_Value &delay,
+ const ACE_Time_Value &interval = ACE_Time_Value::zero);
// Schedule an <event_handler> that will expire after <delay> amount
// of time. If it expires then <arg> is passed in as the value to
// the <event_handler>'s <handle_timeout> callback method. If
diff --git a/ace/Timer_Queue.cpp b/ace/Timer_Queue.cpp
index 5566d1f3b2b..c63169e772e 100644
--- a/ace/Timer_Queue.cpp
+++ b/ace/Timer_Queue.cpp
@@ -107,6 +107,10 @@ ACE_Timer_Queue::ACE_Timer_Queue (void)
ACE_TRACE ("ACE_Timer_Queue::ACE_Timer_Queue");
}
+ACE_Timer_Queue::~ACE_Timer_Queue (void)
+{
+ ACE_TRACE ("ACE_Timer_Queue::~ACE_Timer_Queue");
+}
// Run the <handle_timeout> method for all Timers whose values are <=
// <cur_time>.
@@ -119,7 +123,7 @@ ACE_Timer_Queue::expire (const ACE_Time_Value &cur_time)
int number_of_timers_expired = 0;
- ACE_Timer_Queue_Iterator &iter = this->iter ();
+ ACE_Timer_Queue_Iterator &iter (this->iter ());
// Keep looping while there are timers remaining and the earliest
// timer is <= the <cur_time> passed in to the method.
diff --git a/ace/Timer_Queue.h b/ace/Timer_Queue.h
index 14c2440ae00..75c1c76874c 100644
--- a/ace/Timer_Queue.h
+++ b/ace/Timer_Queue.h
@@ -95,7 +95,7 @@ public:
};
class ACE_Export ACE_Timer_Queue
- // = TITLE
+ // = TITLE
// Provides an interface to timers.
//
// = DESCRIPTION
@@ -116,6 +116,10 @@ public:
ACE_Timer_Queue (void);
// Default constructor.
+ virtual ~ACE_Timer_Queue (void);
+ // Destructor - make virtual for proper destruction of inherited
+ // classes.
+
virtual int is_empty (void) const = 0;
// True if queue is empty, else false.
diff --git a/tests/Timer_Queue_Test.cpp b/tests/Timer_Queue_Test.cpp
index ce58a98aa76..5509d3bb46b 100644
--- a/tests/Timer_Queue_Test.cpp
+++ b/tests/Timer_Queue_Test.cpp
@@ -26,7 +26,7 @@
#include "test_config.h"
// Number of iterations for the performance tests.
-static int max_iterations = ACE_DEFAULT_TIMERS;
+static int max_iterations = ACE_DEFAULT_TIMERS * 100 ;
// Keep track of the timer ids that were assigned to us.
static int *timer_ids = 0;
@@ -106,7 +106,7 @@ test_performance (ACE_Timer_Queue *tq,
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.real_time / double (max_iterations)) * 1000000));
+ (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
@@ -128,7 +128,7 @@ test_performance (ACE_Timer_Queue *tq,
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.real_time / double (max_iterations)) * 1000000));
+ (et.user_time / double (max_iterations)) * 1000000));
// Test the amount of time required to schedule and expire all the
// timers.
@@ -152,7 +152,7 @@ test_performance (ACE_Timer_Queue *tq,
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.real_time / double (max_iterations)) * 1000000));
+ (et.user_time / double (max_iterations)) * 1000000));
}
struct Timer_Queues
@@ -182,12 +182,14 @@ main (int argc, char *argv[])
// Preallocate memory.
ACE_NEW_RETURN (timer_queues[0].queue_,
- ACE_Timer_Heap (max_iterations, 1),
+ ACE_Timer_Heap (ACE_DEFAULT_TIMERS, 1),
+// ACE_Timer_Heap (max_iterations, 1),
-1);
// Don't preallocate memory.
ACE_NEW_RETURN (timer_queues[1].queue_,
- ACE_Timer_Heap (max_iterations),
+ ACE_Timer_Heap,
+// ACE_Timer_Heap (max_iterations),
-1);
ACE_NEW_RETURN (timer_ids,