diff options
-rw-r--r-- | ChangeLog-97a | 10 | ||||
-rw-r--r-- | ace/Timer_Heap.cpp | 102 | ||||
-rw-r--r-- | ace/Timer_Heap.h | 15 | ||||
-rw-r--r-- | ace/Timer_List.cpp | 4 | ||||
-rw-r--r-- | ace/Timer_List.h | 10 | ||||
-rw-r--r-- | ace/Timer_Queue.cpp | 6 | ||||
-rw-r--r-- | ace/Timer_Queue.h | 6 | ||||
-rw-r--r-- | tests/Timer_Queue_Test.cpp | 14 |
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, |