/src/libevent/minheap-internal.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson |
3 | | * |
4 | | * Copyright (c) 2006 Maxim Yegorushkin <maxim.yegorushkin@gmail.com> |
5 | | * |
6 | | * Redistribution and use in source and binary forms, with or without |
7 | | * modification, are permitted provided that the following conditions |
8 | | * are met: |
9 | | * 1. Redistributions of source code must retain the above copyright |
10 | | * notice, this list of conditions and the following disclaimer. |
11 | | * 2. Redistributions in binary form must reproduce the above copyright |
12 | | * notice, this list of conditions and the following disclaimer in the |
13 | | * documentation and/or other materials provided with the distribution. |
14 | | * 3. The name of the author may not be used to endorse or promote products |
15 | | * derived from this software without specific prior written permission. |
16 | | * |
17 | | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 | | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
22 | | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | | */ |
28 | | #ifndef MINHEAP_INTERNAL_H_INCLUDED_ |
29 | | #define MINHEAP_INTERNAL_H_INCLUDED_ |
30 | | |
31 | | #include "event2/event-config.h" |
32 | | #include "evconfig-private.h" |
33 | | #include "event2/event.h" |
34 | | #include "event2/event_struct.h" |
35 | | #include "event2/util.h" |
36 | | #include "util-internal.h" |
37 | | #include "mm-internal.h" |
38 | | |
39 | | typedef struct min_heap |
40 | | { |
41 | | struct event** p; |
42 | | unsigned n, a; |
43 | | } min_heap_t; |
44 | | |
45 | | static inline void min_heap_ctor_(min_heap_t* s); |
46 | | static inline void min_heap_dtor_(min_heap_t* s); |
47 | | static inline void min_heap_elem_init_(struct event* e); |
48 | | static inline int min_heap_elt_is_top_(const struct event *e); |
49 | | static inline int min_heap_empty_(min_heap_t* s); |
50 | | static inline unsigned min_heap_size_(min_heap_t* s); |
51 | | static inline struct event* min_heap_top_(min_heap_t* s); |
52 | | static inline int min_heap_reserve_(min_heap_t* s, unsigned n); |
53 | | static inline int min_heap_push_(min_heap_t* s, struct event* e); |
54 | | static inline struct event* min_heap_pop_(min_heap_t* s); |
55 | | static inline int min_heap_adjust_(min_heap_t *s, struct event* e); |
56 | | static inline int min_heap_erase_(min_heap_t* s, struct event* e); |
57 | | static inline void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e); |
58 | | static inline void min_heap_shift_up_unconditional_(min_heap_t* s, unsigned hole_index, struct event* e); |
59 | | static inline void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e); |
60 | | |
61 | | #define min_heap_elem_greater(a, b) \ |
62 | 0 | (evutil_timercmp(&(a)->ev_timeout, &(b)->ev_timeout, >)) |
63 | | |
64 | 0 | void min_heap_ctor_(min_heap_t* s) { s->p = 0; s->n = 0; s->a = 0; } Unexecuted instantiation: event.c:min_heap_ctor_ Unexecuted instantiation: evmap.c:min_heap_ctor_ Unexecuted instantiation: select.c:min_heap_ctor_ Unexecuted instantiation: poll.c:min_heap_ctor_ Unexecuted instantiation: epoll.c:min_heap_ctor_ Unexecuted instantiation: signal.c:min_heap_ctor_ |
65 | 0 | void min_heap_dtor_(min_heap_t* s) { if (s->p) mm_free(s->p); } Unexecuted instantiation: event.c:min_heap_dtor_ Unexecuted instantiation: evmap.c:min_heap_dtor_ Unexecuted instantiation: select.c:min_heap_dtor_ Unexecuted instantiation: poll.c:min_heap_dtor_ Unexecuted instantiation: epoll.c:min_heap_dtor_ Unexecuted instantiation: signal.c:min_heap_dtor_ |
66 | 0 | void min_heap_elem_init_(struct event* e) { e->ev_timeout_pos.min_heap_idx = -1; } Unexecuted instantiation: event.c:min_heap_elem_init_ Unexecuted instantiation: evmap.c:min_heap_elem_init_ Unexecuted instantiation: select.c:min_heap_elem_init_ Unexecuted instantiation: poll.c:min_heap_elem_init_ Unexecuted instantiation: epoll.c:min_heap_elem_init_ Unexecuted instantiation: signal.c:min_heap_elem_init_ |
67 | 0 | int min_heap_empty_(min_heap_t* s) { return 0u == s->n; } Unexecuted instantiation: event.c:min_heap_empty_ Unexecuted instantiation: evmap.c:min_heap_empty_ Unexecuted instantiation: select.c:min_heap_empty_ Unexecuted instantiation: poll.c:min_heap_empty_ Unexecuted instantiation: epoll.c:min_heap_empty_ Unexecuted instantiation: signal.c:min_heap_empty_ |
68 | 0 | unsigned min_heap_size_(min_heap_t* s) { return s->n; } Unexecuted instantiation: event.c:min_heap_size_ Unexecuted instantiation: evmap.c:min_heap_size_ Unexecuted instantiation: select.c:min_heap_size_ Unexecuted instantiation: poll.c:min_heap_size_ Unexecuted instantiation: epoll.c:min_heap_size_ Unexecuted instantiation: signal.c:min_heap_size_ |
69 | 0 | struct event* min_heap_top_(min_heap_t* s) { return s->n ? *s->p : 0; } Unexecuted instantiation: event.c:min_heap_top_ Unexecuted instantiation: evmap.c:min_heap_top_ Unexecuted instantiation: select.c:min_heap_top_ Unexecuted instantiation: poll.c:min_heap_top_ Unexecuted instantiation: epoll.c:min_heap_top_ Unexecuted instantiation: signal.c:min_heap_top_ |
70 | | |
71 | | int min_heap_push_(min_heap_t* s, struct event* e) |
72 | 0 | { |
73 | 0 | if (min_heap_reserve_(s, s->n + 1)) |
74 | 0 | return -1; |
75 | 0 | min_heap_shift_up_(s, s->n++, e); |
76 | 0 | return 0; |
77 | 0 | } Unexecuted instantiation: event.c:min_heap_push_ Unexecuted instantiation: evmap.c:min_heap_push_ Unexecuted instantiation: select.c:min_heap_push_ Unexecuted instantiation: poll.c:min_heap_push_ Unexecuted instantiation: epoll.c:min_heap_push_ Unexecuted instantiation: signal.c:min_heap_push_ |
78 | | |
79 | | struct event* min_heap_pop_(min_heap_t* s) |
80 | 0 | { |
81 | 0 | if (s->n) |
82 | 0 | { |
83 | 0 | struct event* e = *s->p; |
84 | 0 | min_heap_shift_down_(s, 0u, s->p[--s->n]); |
85 | 0 | e->ev_timeout_pos.min_heap_idx = -1; |
86 | 0 | return e; |
87 | 0 | } |
88 | 0 | return 0; |
89 | 0 | } Unexecuted instantiation: event.c:min_heap_pop_ Unexecuted instantiation: evmap.c:min_heap_pop_ Unexecuted instantiation: select.c:min_heap_pop_ Unexecuted instantiation: poll.c:min_heap_pop_ Unexecuted instantiation: epoll.c:min_heap_pop_ Unexecuted instantiation: signal.c:min_heap_pop_ |
90 | | |
91 | | int min_heap_elt_is_top_(const struct event *e) |
92 | 0 | { |
93 | 0 | return e->ev_timeout_pos.min_heap_idx == 0; |
94 | 0 | } Unexecuted instantiation: event.c:min_heap_elt_is_top_ Unexecuted instantiation: evmap.c:min_heap_elt_is_top_ Unexecuted instantiation: select.c:min_heap_elt_is_top_ Unexecuted instantiation: poll.c:min_heap_elt_is_top_ Unexecuted instantiation: epoll.c:min_heap_elt_is_top_ Unexecuted instantiation: signal.c:min_heap_elt_is_top_ |
95 | | |
96 | | int min_heap_erase_(min_heap_t* s, struct event* e) |
97 | 0 | { |
98 | 0 | if (-1 != e->ev_timeout_pos.min_heap_idx) |
99 | 0 | { |
100 | 0 | struct event *last = s->p[--s->n]; |
101 | 0 | unsigned parent = (e->ev_timeout_pos.min_heap_idx - 1) / 2; |
102 | 0 | /* we replace e with the last element in the heap. We might need to |
103 | 0 | shift it upward if it is less than its parent, or downward if it is |
104 | 0 | greater than one or both its children. Since the children are known |
105 | 0 | to be less than the parent, it can't need to shift both up and |
106 | 0 | down. */ |
107 | 0 | if (e->ev_timeout_pos.min_heap_idx > 0 && min_heap_elem_greater(s->p[parent], last)) |
108 | 0 | min_heap_shift_up_unconditional_(s, e->ev_timeout_pos.min_heap_idx, last); |
109 | 0 | else |
110 | 0 | min_heap_shift_down_(s, e->ev_timeout_pos.min_heap_idx, last); |
111 | 0 | e->ev_timeout_pos.min_heap_idx = -1; |
112 | 0 | return 0; |
113 | 0 | } |
114 | 0 | return -1; |
115 | 0 | } Unexecuted instantiation: event.c:min_heap_erase_ Unexecuted instantiation: evmap.c:min_heap_erase_ Unexecuted instantiation: select.c:min_heap_erase_ Unexecuted instantiation: poll.c:min_heap_erase_ Unexecuted instantiation: epoll.c:min_heap_erase_ Unexecuted instantiation: signal.c:min_heap_erase_ |
116 | | |
117 | | int min_heap_adjust_(min_heap_t *s, struct event *e) |
118 | 0 | { |
119 | 0 | if (-1 == e->ev_timeout_pos.min_heap_idx) { |
120 | 0 | return min_heap_push_(s, e); |
121 | 0 | } else { |
122 | 0 | unsigned parent = (e->ev_timeout_pos.min_heap_idx - 1) / 2; |
123 | 0 | /* The position of e has changed; we shift it up or down |
124 | 0 | * as needed. We can't need to do both. */ |
125 | 0 | if (e->ev_timeout_pos.min_heap_idx > 0 && min_heap_elem_greater(s->p[parent], e)) |
126 | 0 | min_heap_shift_up_unconditional_(s, e->ev_timeout_pos.min_heap_idx, e); |
127 | 0 | else |
128 | 0 | min_heap_shift_down_(s, e->ev_timeout_pos.min_heap_idx, e); |
129 | 0 | return 0; |
130 | 0 | } |
131 | 0 | } Unexecuted instantiation: event.c:min_heap_adjust_ Unexecuted instantiation: evmap.c:min_heap_adjust_ Unexecuted instantiation: select.c:min_heap_adjust_ Unexecuted instantiation: poll.c:min_heap_adjust_ Unexecuted instantiation: epoll.c:min_heap_adjust_ Unexecuted instantiation: signal.c:min_heap_adjust_ |
132 | | |
133 | | int min_heap_reserve_(min_heap_t* s, unsigned n) |
134 | 0 | { |
135 | 0 | if (s->a < n) |
136 | 0 | { |
137 | 0 | struct event** p; |
138 | 0 | unsigned a = s->a ? s->a * 2 : 8; |
139 | 0 | if (a < n) |
140 | 0 | a = n; |
141 | 0 | if (!(p = (struct event**)mm_realloc(s->p, a * sizeof *p))) |
142 | 0 | return -1; |
143 | 0 | s->p = p; |
144 | 0 | s->a = a; |
145 | 0 | } |
146 | 0 | return 0; |
147 | 0 | } Unexecuted instantiation: event.c:min_heap_reserve_ Unexecuted instantiation: evmap.c:min_heap_reserve_ Unexecuted instantiation: select.c:min_heap_reserve_ Unexecuted instantiation: poll.c:min_heap_reserve_ Unexecuted instantiation: epoll.c:min_heap_reserve_ Unexecuted instantiation: signal.c:min_heap_reserve_ |
148 | | |
149 | | void min_heap_shift_up_unconditional_(min_heap_t* s, unsigned hole_index, struct event* e) |
150 | 0 | { |
151 | 0 | unsigned parent = (hole_index - 1) / 2; |
152 | 0 | do |
153 | 0 | { |
154 | 0 | (s->p[hole_index] = s->p[parent])->ev_timeout_pos.min_heap_idx = hole_index; |
155 | 0 | hole_index = parent; |
156 | 0 | parent = (hole_index - 1) / 2; |
157 | 0 | } while (hole_index && min_heap_elem_greater(s->p[parent], e)); |
158 | 0 | (s->p[hole_index] = e)->ev_timeout_pos.min_heap_idx = hole_index; |
159 | 0 | } Unexecuted instantiation: event.c:min_heap_shift_up_unconditional_ Unexecuted instantiation: evmap.c:min_heap_shift_up_unconditional_ Unexecuted instantiation: select.c:min_heap_shift_up_unconditional_ Unexecuted instantiation: poll.c:min_heap_shift_up_unconditional_ Unexecuted instantiation: epoll.c:min_heap_shift_up_unconditional_ Unexecuted instantiation: signal.c:min_heap_shift_up_unconditional_ |
160 | | |
161 | | void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e) |
162 | 0 | { |
163 | 0 | unsigned parent = (hole_index - 1) / 2; |
164 | 0 | while (hole_index && min_heap_elem_greater(s->p[parent], e)) |
165 | 0 | { |
166 | 0 | (s->p[hole_index] = s->p[parent])->ev_timeout_pos.min_heap_idx = hole_index; |
167 | 0 | hole_index = parent; |
168 | 0 | parent = (hole_index - 1) / 2; |
169 | 0 | } |
170 | 0 | (s->p[hole_index] = e)->ev_timeout_pos.min_heap_idx = hole_index; |
171 | 0 | } Unexecuted instantiation: event.c:min_heap_shift_up_ Unexecuted instantiation: evmap.c:min_heap_shift_up_ Unexecuted instantiation: select.c:min_heap_shift_up_ Unexecuted instantiation: poll.c:min_heap_shift_up_ Unexecuted instantiation: epoll.c:min_heap_shift_up_ Unexecuted instantiation: signal.c:min_heap_shift_up_ |
172 | | |
173 | | void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e) |
174 | 0 | { |
175 | 0 | unsigned min_child = 2 * (hole_index + 1); |
176 | 0 | while (min_child <= s->n) |
177 | 0 | { |
178 | 0 | min_child -= min_child == s->n || min_heap_elem_greater(s->p[min_child], s->p[min_child - 1]); |
179 | 0 | if (!(min_heap_elem_greater(e, s->p[min_child]))) |
180 | 0 | break; |
181 | 0 | (s->p[hole_index] = s->p[min_child])->ev_timeout_pos.min_heap_idx = hole_index; |
182 | 0 | hole_index = min_child; |
183 | 0 | min_child = 2 * (hole_index + 1); |
184 | 0 | } |
185 | 0 | (s->p[hole_index] = e)->ev_timeout_pos.min_heap_idx = hole_index; |
186 | 0 | } Unexecuted instantiation: event.c:min_heap_shift_down_ Unexecuted instantiation: evmap.c:min_heap_shift_down_ Unexecuted instantiation: select.c:min_heap_shift_down_ Unexecuted instantiation: poll.c:min_heap_shift_down_ Unexecuted instantiation: epoll.c:min_heap_shift_down_ Unexecuted instantiation: signal.c:min_heap_shift_down_ |
187 | | |
188 | | #endif /* MINHEAP_INTERNAL_H_INCLUDED_ */ |