]> granicus.if.org Git - libevent/commitdiff
Fix min_heap_erase when we remove an element from the middle of the heap.
authorNick Mathewson <nickm@torproject.org>
Thu, 23 Apr 2009 00:01:24 +0000 (00:01 +0000)
committerNick Mathewson <nickm@torproject.org>
Thu, 23 Apr 2009 00:01:24 +0000 (00:01 +0000)
Previously, we could lose the heap property when we removed an item
whose parent was greater than the last element in the heap.  We would
replace the removed item with the last element, and consider shifting
it down, but we wouldn't consider shifting it up.

Patch from Marko Kreen.

svn:r1226

ChangeLog
minheap-internal.h

index aea64512c9710696d62902bb59200590d9bf26a5..a8f77200c3141bd9b67484bc256be0d95513038b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,7 @@ Changes in 2.0.2-alpha:
  o Fix a possible free(NULL) when freeing an event_base with no signals.
  o Add a flag to disable checking environment varibles when making an event_base
  o Disallow setting less than 1 priority.
+ o Fix a bug when removing a timeout from the heap. [Patch from Marko Kreen]
 
 Changes in 2.0.1-alpha:
  o free minheap on event_base_free(); from Christopher Layne
index 6cd9c4aa121d33f732e375b0840330e9d3e62056..3b2870430bbc2d48597d95b122e31e9769bc6417 100644 (file)
@@ -88,7 +88,17 @@ int min_heap_erase(min_heap_t* s, struct event* e)
 {
     if(((unsigned int)-1) != e->min_heap_idx)
     {
-        min_heap_shift_down_(s, e->min_heap_idx, s->p[--s->n]);
+        struct event *last = s->p[--s->n];
+        unsigned parent = (e->min_heap_idx - 1) / 2;
+       /* we replace e with the last element in the heap.  We might need to
+          shift it upward if it is less than its parent, or downward if it is
+          greater than one or both its children. Since the children are known
+          to be less than the parent, it can't need to shift both up and
+          down. */
+        if (e->min_heap_idx > 0 && min_heap_elem_greater(s->p[parent], last))
+             min_heap_shift_up_(s, e->min_heap_idx, last);
+        else
+             min_heap_shift_down_(s, e->min_heap_idx, last);
         e->min_heap_idx = -1;
         return 0;
     }