2 This file is part of PulseAudio.
4 Copyright 2008 Lennart Poettering
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License,
9 or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 #include <pulse/xmalloc.h>
28 #include <pulsecore/flist.h>
32 struct pa_prioq_item
{
38 pa_prioq_item
**items
;
41 pa_compare_func_t compare_func
;
44 PA_STATIC_FLIST_DECLARE(items
, 0, pa_xfree
);
46 pa_prioq
*pa_prioq_new(pa_compare_func_t compare_func
) {
50 q
= pa_xnew(pa_prioq
, 1);
51 q
->compare_func
= compare_func
;
54 q
->items
= pa_xnew(pa_prioq_item
*, q
->n_allocated
);
59 void pa_prioq_free(pa_prioq
*q
, pa_free2_cb_t free_cb
, void *userdata
) {
60 pa_prioq_item
**i
, **e
;
64 for (i
= q
->items
, e
= q
->items
+ q
->n_items
; i
< e
; i
++) {
70 free_cb((*i
)->value
, userdata
);
79 static void shuffle_up(pa_prioq
*q
, pa_prioq_item
*i
) {
92 if (q
->compare_func(q
->items
[k
]->value
, i
->value
) < 0)
96 q
->items
[j
] = q
->items
[k
];
106 pa_prioq_item
* pa_prioq_put(pa_prioq
*q
, void *p
) {
111 if (q
->n_items
>= q
->n_allocated
) {
112 q
->n_allocated
= PA_MAX(q
->n_items
+1, q
->n_allocated
)*2;
113 q
->items
= pa_xrealloc(q
->items
, sizeof(pa_prioq_item
*) * q
->n_allocated
);
116 if (!(i
= pa_flist_pop(PA_STATIC_FLIST_GET(items
))))
117 i
= pa_xnew(pa_prioq_item
, 1);
120 i
->idx
= q
->n_items
++;
127 void* pa_prioq_peek(pa_prioq
*q
) {
133 return q
->items
[0]->value
;
136 void* pa_prioq_pop(pa_prioq
*q
){
142 return pa_prioq_remove(q
, q
->items
[0]);
145 static void swap(pa_prioq
*q
, unsigned j
, unsigned k
) {
149 pa_assert(j
< q
->n_items
);
150 pa_assert(k
< q
->n_items
);
152 pa_assert(q
->items
[j
]->idx
== j
);
153 pa_assert(q
->items
[k
]->idx
== k
);
157 q
->items
[j
]->idx
= k
;
158 q
->items
[j
] = q
->items
[k
];
160 q
->items
[k
]->idx
= j
;
164 static void shuffle_down(pa_prioq
*q
, unsigned idx
) {
167 pa_assert(idx
< q
->n_items
);
172 k
= (idx
+1)*2; /* right child */
173 j
= k
-1; /* left child */
178 if (q
->compare_func(q
->items
[j
]->value
, q
->items
[idx
]->value
) < 0)
180 /* So our left child is smaller than we are, let's
181 * remember this fact */
186 if (k
< q
->n_items
&&
187 q
->compare_func(q
->items
[k
]->value
, q
->items
[s
]->value
) < 0)
189 /* So our right child is smaller than we are, let's
190 * remember this fact */
193 /* s now points to the smallest of the three items */
196 /* No swap necessary, we're done */
204 void* pa_prioq_remove(pa_prioq
*q
, pa_prioq_item
*i
) {
209 pa_assert(q
->n_items
>= 1);
213 if (q
->n_items
-1 == i
->idx
) {
214 /* We are the last entry, so let's just remove us and good */
219 /* We are not the last entry, we need to replace ourselves
220 * with the last node and reshuffle */
222 q
->items
[i
->idx
] = q
->items
[q
->n_items
-1];
223 q
->items
[i
->idx
]->idx
= i
->idx
;
226 shuffle_down(q
, i
->idx
);
229 if (pa_flist_push(PA_STATIC_FLIST_GET(items
), i
) < 0)
235 unsigned pa_prioq_size(pa_prioq
*q
) {
241 pa_bool_t
pa_prioq_isempty(pa_prioq
*q
) {
244 return q
->n_items
== 0;
247 void pa_prioq_reshuffle(pa_prioq
*q
, pa_prioq_item
*i
) {
251 /* This will move the entry down as far as necessary */
252 shuffle_down(q
, i
->idx
);
254 /* And this will move the entry up as far as necessary */