1 : /*
2 : * Copyright (c) 2006 Maxim Yegorushkin <maxim.yegorushkin@gmail.com>
3 : * All rights reserved.
4 : *
5 : * Redistribution and use in source and binary forms, with or without
6 : * modification, are permitted provided that the following conditions
7 : * are met:
8 : * 1. Redistributions of source code must retain the above copyright
9 : * notice, this list of conditions and the following disclaimer.
10 : * 2. Redistributions in binary form must reproduce the above copyright
11 : * notice, this list of conditions and the following disclaimer in the
12 : * documentation and/or other materials provided with the distribution.
13 : * 3. The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 : *
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #ifndef _MIN_HEAP_H_
28 : #define _MIN_HEAP_H_
29 :
30 : #include "event.h"
31 : #include "evutil.h"
32 :
33 : typedef struct min_heap
34 : {
35 : struct event** p;
36 : unsigned n, a;
37 : } min_heap_t;
38 :
39 : static inline void min_heap_ctor(min_heap_t* s);
40 : static inline void min_heap_dtor(min_heap_t* s);
41 : static inline void min_heap_elem_init(struct event* e);
42 : static inline int min_heap_elem_greater(struct event *a, struct event *b);
43 : static inline int min_heap_empty(min_heap_t* s);
44 : static inline unsigned min_heap_size(min_heap_t* s);
45 : static inline struct event* min_heap_top(min_heap_t* s);
46 : static inline int min_heap_reserve(min_heap_t* s, unsigned n);
47 : static inline int min_heap_push(min_heap_t* s, struct event* e);
48 : static inline struct event* min_heap_pop(min_heap_t* s);
49 : static inline int min_heap_erase(min_heap_t* s, struct event* e);
50 : static inline void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e);
51 : static inline void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e);
52 :
53 0 : int min_heap_elem_greater(struct event *a, struct event *b)
54 : {
55 0 : return evutil_timercmp(&a->ev_timeout, &b->ev_timeout, >);
56 : }
57 :
58 1420 : void min_heap_ctor(min_heap_t* s) { s->p = 0; s->n = 0; s->a = 0; }
59 1419 : void min_heap_dtor(min_heap_t* s) { free(s->p); }
60 2840 : void min_heap_elem_init(struct event* e) { e->min_heap_idx = -1; }
61 2890 : int min_heap_empty(min_heap_t* s) { return 0u == s->n; }
62 0 : unsigned min_heap_size(min_heap_t* s) { return s->n; }
63 2891 : struct event* min_heap_top(min_heap_t* s) { return s->n ? *s->p : 0; }
64 :
65 0 : int min_heap_push(min_heap_t* s, struct event* e)
66 : {
67 0 : if(min_heap_reserve(s, s->n + 1))
68 0 : return -1;
69 0 : min_heap_shift_up_(s, s->n++, e);
70 0 : return 0;
71 : }
72 :
73 : struct event* min_heap_pop(min_heap_t* s)
74 : {
75 : if(s->n)
76 : {
77 : struct event* e = *s->p;
78 : min_heap_shift_down_(s, 0u, s->p[--s->n]);
79 : e->min_heap_idx = -1;
80 : return e;
81 : }
82 : return 0;
83 : }
84 :
85 0 : int min_heap_erase(min_heap_t* s, struct event* e)
86 : {
87 0 : if(((unsigned int)-1) != e->min_heap_idx)
88 : {
89 0 : min_heap_shift_down_(s, e->min_heap_idx, s->p[--s->n]);
90 0 : e->min_heap_idx = -1;
91 0 : return 0;
92 : }
93 0 : return -1;
94 : }
95 :
96 0 : int min_heap_reserve(min_heap_t* s, unsigned n)
97 : {
98 0 : if(s->a < n)
99 : {
100 : struct event** p;
101 0 : unsigned a = s->a ? s->a * 2 : 8;
102 0 : if(a < n)
103 0 : a = n;
104 0 : if(!(p = (struct event**)realloc(s->p, a * sizeof *p)))
105 0 : return -1;
106 0 : s->p = p;
107 0 : s->a = a;
108 : }
109 0 : return 0;
110 : }
111 :
112 0 : void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e)
113 : {
114 0 : unsigned parent = (hole_index - 1) / 2;
115 0 : while(hole_index && min_heap_elem_greater(s->p[parent], e))
116 : {
117 0 : (s->p[hole_index] = s->p[parent])->min_heap_idx = hole_index;
118 0 : hole_index = parent;
119 0 : parent = (hole_index - 1) / 2;
120 : }
121 0 : (s->p[hole_index] = e)->min_heap_idx = hole_index;
122 0 : }
123 :
124 0 : void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e)
125 : {
126 0 : unsigned min_child = 2 * (hole_index + 1);
127 0 : while(min_child <= s->n)
128 : {
129 0 : min_child -= min_child == s->n || min_heap_elem_greater(s->p[min_child], s->p[min_child - 1]);
130 0 : if(!(min_heap_elem_greater(e, s->p[min_child])))
131 0 : break;
132 0 : (s->p[hole_index] = s->p[min_child])->min_heap_idx = hole_index;
133 0 : hole_index = min_child;
134 0 : min_child = 2 * (hole_index + 1);
135 : }
136 0 : min_heap_shift_up_(s, hole_index, e);
137 0 : }
138 :
139 : #endif /* _MIN_HEAP_H_ */
|