1 /* pq.c - priority queue */
3 /* Copyright (C) 2007 Keith Rarick and Philotic Inc.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "tube.h" /* hack to make cpp happy */
27 pq_init(pq q
, job_cmp_fn cmp
)
50 unsigned int ncap
= q
->cap
<< 1 ? : 1;
52 nheap
= malloc(ncap
* sizeof(job
));
55 if (q
->heap
) memcpy(nheap
, q
->heap
, q
->used
* sizeof(job
));
62 swap(pq q
, unsigned int a
, unsigned int b
)
67 q
->heap
[a
] = q
->heap
[b
];
70 q
->heap
[a
]->heap_index
= a
;
71 q
->heap
[b
]->heap_index
= b
;
74 #define PARENT(i) (((i-1))>>1)
75 #define CHILD_LEFT(i) (((i)<<1)+1)
76 #define CHILD_RIGHT(i) (((i)<<1)+2)
79 cmp(pq q
, unsigned int a
, unsigned int b
)
81 return q
->cmp(q
->heap
[a
], q
->heap
[b
]);
85 bubble_up(pq q
, unsigned int k
)
91 if (cmp(q
, p
, k
) <= 0) return;
97 bubble_down(pq q
, unsigned int k
)
105 if (l
< q
->used
&& cmp(q
, l
, k
) < 0) s
= l
;
106 if (r
< q
->used
&& cmp(q
, r
, s
) < 0) s
= r
;
107 if (s
== k
) return; /* already satisfies the heap property */
113 /* assumes there is at least one item in the queue */
117 q
->heap
[0] = q
->heap
[--q
->used
];
118 q
->heap
[0]->heap_index
= 0;
119 if (q
->used
) bubble_down(q
, 0);
127 if (q
->used
>= q
->cap
) pq_grow(q
);
128 if (q
->used
>= q
->cap
) return 0;
143 if (q
->used
== 0) return NULL
;
153 if (q
->used
== 0) return NULL
;
158 pq_remove(pq q
, job j
)
163 if (j
->heap_index
>= q
->used
) return NULL
;
164 if (q
->heap
[j
->heap_index
] != j
) return NULL
;
171 bubble_up(q
, j
->heap_index
);
177 if (q
->heap
[0] != j
) return NULL
;