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