summaryrefslogtreecommitdiff
path: root/minheap-internal.h
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2009-04-23 00:01:24 +0000
committerNick Mathewson <nickm@torproject.org>2009-04-23 00:01:24 +0000
commit8b7a3b3676375d145e0b89d3f3d9194c7031a760 (patch)
treed346a0df9b85e435985fbe592526b84272f32bbb /minheap-internal.h
parent0068c98ad2653c3ed3ac70250893531d072c2fbb (diff)
downloadlibevent-8b7a3b3676375d145e0b89d3f3d9194c7031a760.tar.gz
Fix min_heap_erase when we remove an element from the middle of the heap.
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
Diffstat (limited to 'minheap-internal.h')
-rw-r--r--minheap-internal.h12
1 files changed, 11 insertions, 1 deletions
diff --git a/minheap-internal.h b/minheap-internal.h
index 6cd9c4aa..3b287043 100644
--- a/minheap-internal.h
+++ b/minheap-internal.h
@@ -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;
}