summaryrefslogtreecommitdiff
path: root/ace/Timer_Heap.cpp
diff options
context:
space:
mode:
authorschmidt <douglascraigschmidt@users.noreply.github.com>1997-01-13 06:53:56 +0000
committerschmidt <douglascraigschmidt@users.noreply.github.com>1997-01-13 06:53:56 +0000
commit9a4015e3745ffdcabce4aefb7306f1e685005b0f (patch)
treeef38939ea1d530093d0ddde463a80f052577941a /ace/Timer_Heap.cpp
parente3a0ffa03433e389ca436b5b749fcb70950c4409 (diff)
downloadATCD-9a4015e3745ffdcabce4aefb7306f1e685005b0f.tar.gz
foo
Diffstat (limited to 'ace/Timer_Heap.cpp')
-rw-r--r--ace/Timer_Heap.cpp143
1 files changed, 109 insertions, 34 deletions
diff --git a/ace/Timer_Heap.cpp b/ace/Timer_Heap.cpp
index b69872928eb..f32ab68bf88 100644
--- a/ace/Timer_Heap.cpp
+++ b/ace/Timer_Heap.cpp
@@ -14,15 +14,9 @@ ACE_Timer_Heap_Iterator::next (ACE_Timer_Node *&node,
return 0;
else
{
- node = this->timer_heap_.heap_[0];
+ // Remove the first item and restore the heap property.
- // Transfer the last element in the heap to the front and
- // restore the heap property.
-
- this->timer_heap_.heap_[0] =
- this->timer_heap_.heap_[--this->timer_heap_.cur_size_];
-
- this->timer_heap_.reheap_down ();
+ node = this->timer_heap_.remove (0);
return 1;
}
}
@@ -72,49 +66,93 @@ ACE_Timer_Heap::dump (void) const
this->heap_[index]->dump ();
}
-void
-ACE_Timer_Heap::reheap_down (void)
+ACE_Timer_Node *
+ACE_Timer_Heap::remove (int index)
+{
+ ACE_Timer_Node *result = this->heap_[index];
+
+ this->cur_size_--;
+
+ // Only try to reheapify if we're not deleting the last entry.
+
+ if (index < this->cur_size_)
+ {
+ // Move the end node to the location being removed.
+ this->heap_[index] = this->heap_[this->cur_size_];
+
+ ACE_Timer_Node *moved_node = this->heap_[index];
+
+ // If we're at the top there's no place to go but down!
+ if (index == 0)
+ this->reheap_down (moved_node, 1);
+
+ // If the moved_node->time_value_ is smaller than its parent it
+ // needs be moved up the heap.
+ else if (moved_node->timer_value_ < this->heap_[(index - 1) / 2]->timer_value_)
+ this->reheap_up (moved_node);
+
+ // Call <reheap_down>, which will reheapify if the
+ // moved_node->time_value_ is larger than either of its children
+ // (who start at location <index + index>).
+ else
+ this->reheap_down (moved_node, index + index);
+ }
+
+ return result;
+}
+
+void
+ACE_Timer_Heap::reheap_down (ACE_Timer_Node *moved_node,
+ int child_index)
{
int parent = 0;
- int child = 1;
- ACE_Timer_Node *temp = this->heap_[parent];
- // Restore the heap property.
+ // Restore the heap property after a deletion.
- while (child < this->cur_size_)
+ for (int child = child_index;
+ child < this->cur_size_;
+ child += child + 1) // Multiple child by 2 and add 1.
{
+ // 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]->timer_value_ < this->heap_[child]->timer_value_)
child++;
- if (this->heap_[child]->timer_value_ > temp->timer_value_)
+ // Perform a swap if the child has a larger timeout value than
+ // the front node.
+ if (this->heap_[child]->timer_value_ < moved_node->timer_value_)
{
this->heap_[parent] = this->heap_[child];
parent = child;
- // Multiple child by 2 and add 1.
- child += child + 1;
}
else
break;
}
- this->heap_[parent] = temp;
+ // Insert moved_node into its final resting place.
+ this->heap_[parent] = moved_node;
+}
+
+void
+ACE_Timer_Heap::insert (ACE_Timer_Node *new_node)
+{
+ this->reheap_up (new_node);
+ this->cur_size_++;
}
void
-ACE_Timer_Heap::reheap_up (void)
+ACE_Timer_Heap::reheap_up (ACE_Timer_Node *new_node)
{
int parent;
- int child = this->cur_size_ - 1;
- ACE_Timer_Node *temp = this->heap_[child];
-
- // Restore the heap property.
+ int child = this->cur_size_;
+
+ // Restore the heap property after an insertion.
while (child > 0)
{
parent = (child - 1) / 2;
- if (temp->timer_value_ < this->heap_[parent]->timer_value_)
+ if (new_node->timer_value_ < this->heap_[parent]->timer_value_)
{
this->heap_[child] = this->heap_[parent];
child = parent;
@@ -123,7 +161,7 @@ ACE_Timer_Heap::reheap_up (void)
break;
}
- this->heap_[child] = temp;
+ this->heap_[child] = new_node;
}
// Reschedule a periodic timer. This function must be called with the
@@ -134,10 +172,8 @@ ACE_Timer_Heap::reschedule (ACE_Timer_Node *expired)
{
ACE_TRACE ("ACE_Timer_Heap::reschedule");
- // Insert the <expired> node into the end of the heap and restore
- // the heap property.
- this->heap_[this->cur_size_++] = expired;
- this->reheap_up ();
+ // Restore the heap property.
+ this->insert (expired);
}
// Insert a new handler that expires at time future_time; if interval
@@ -174,7 +210,7 @@ ACE_Timer_Heap::schedule (ACE_Event_Handler *handler,
timer_id),
-1);
- this->reheap_up (temp);
+ this->insert (temp);
}
return timer_id;
@@ -184,12 +220,33 @@ ACE_Timer_Heap::schedule (ACE_Event_Handler *handler,
// <timer_id> from the timer queue.
int
-ACE_Timer_Heap::cancel (int timer_id, const void **arg)
+ACE_Timer_Heap::cancel (int timer_id,
+ const void **arg)
{
ACE_TRACE ("ACE_Timer_Heap::cancel");
ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
- return 0;
+ int i;
+
+ // Try to locate the ACE_Timer_Node that matches the timer_id.
+
+ for (i = 0;
+ i < this->cur_size_ && this->heap_[i]->timer_id_ != timer_id;
+ i++)
+ continue;
+
+ if (i == this->cur_size_)
+ return 0;
+ else
+ {
+ ACE_Timer_Node *temp = this->remove (i);
+
+ if (arg != 0)
+ *arg = temp->arg_;
+
+ delete temp;
+ return 1;
+ }
}
// Locate and remove all values of <handler> from the timer queue.
@@ -200,5 +257,23 @@ ACE_Timer_Heap::cancel (ACE_Event_Handler *handler)
ACE_TRACE ("ACE_Timer_Heap::cancel");
ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
- return 0;
+ int number_of_cancellations = 0;
+
+ // Try to locate the ACE_Timer_Node that matches the timer_id.
+
+ for (int i = 0;
+ i < this->cur_size_;
+ )
+ {
+ if (this->heap_[i]->handler_ == handler)
+ {
+ ACE_Timer_Node *temp = this->remove (i);
+ delete temp;
+ number_of_cancellations++;
+ }
+ else
+ i++;
+ }
+
+ return number_of_cancellations;
}