From 8b7a3b3676375d145e0b89d3f3d9194c7031a760 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 23 Apr 2009 00:01:24 +0000 Subject: [PATCH] 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 --- ChangeLog | 1 + minheap-internal.h | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index aea64512..a8f77200 100644 --- 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 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; } -- 2.50.0