Use z rather than the obsolete Z modifier.
[beanstalkd.git] / pq.c
blob292fa0135819e8ee667431a154c4faea79cb9793
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/>.
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
23 #include "tube.h" /* hack to make cpp happy */
24 #include "pq.h"
26 void
27 pq_init(pq q, job_cmp_fn cmp)
29 if (!q) return;
31 q->cap = 0;
32 q->used = 0;
33 q->cmp = cmp;
34 q->heap = NULL;
36 return;
39 void
40 pq_clear(pq q)
42 free(q->heap);
43 pq_init(q, q->cmp);
46 static void
47 pq_grow(pq q)
49 job *nheap;
50 unsigned int ncap = q->cap << 1 ? : 1;
52 nheap = malloc(ncap * sizeof(job));
53 if (!nheap) return;
55 if (q->heap) memcpy(nheap, q->heap, q->used * sizeof(job));
56 free(q->heap);
57 q->heap = nheap;
58 q->cap = ncap;
61 static void
62 swap(pq q, unsigned int a, unsigned int b)
64 job j;
66 j = q->heap[a];
67 q->heap[a] = q->heap[b];
68 q->heap[b] = j;
71 #define PARENT(i) (((i-1))>>1)
72 #define CHILD_LEFT(i) (((i)<<1)+1)
73 #define CHILD_RIGHT(i) (((i)<<1)+2)
75 static int
76 cmp(pq q, unsigned int a, unsigned int b)
78 return q->cmp(q->heap[a], q->heap[b]);
81 static void
82 bubble_up(pq q, unsigned int k)
84 int p;
86 if (k == 0) return;
87 p = PARENT(k);
88 if (cmp(q, p, k) <= 0) return;
89 swap(q, k, p);
90 bubble_up(q, p);
93 static void
94 bubble_down(pq q, unsigned int k)
96 int l, r, s;
98 l = CHILD_LEFT(k);
99 r = CHILD_RIGHT(k);
101 s = k;
102 if (l < q->used && cmp(q, l, k) < 0) s = l;
103 if (r < q->used && cmp(q, r, s) < 0) s = r;
104 if (s == k) return; /* already satisfies the heap property */
106 swap(q, k, s);
107 bubble_down(q, s);
110 /* assumes there is at least one item in the queue */
111 static void
112 delete_min(pq q)
114 q->heap[0] = q->heap[--q->used];
115 if (q->used) bubble_down(q, 0);
119 pq_give(pq q, job j)
121 int k;
123 if (q->used >= q->cap) pq_grow(q);
124 if (q->used >= q->cap) return 0;
126 k = q->used++;
127 q->heap[k] = j;
128 bubble_up(q, k);
130 return 1;
134 pq_take(pq q)
136 job j;
138 if (q->used == 0) return NULL;
140 j = q->heap[0];
141 delete_min(q);
142 return j;
146 pq_peek(pq q)
148 if (q->used == 0) return NULL;
149 return q->heap[0];
153 pq_find(pq q, unsigned long long int id)
155 unsigned int i;
157 for (i = 0; i < q->used; i++) if (q->heap[i]->id == id) return q->heap[i];
158 return NULL;
161 unsigned int
162 pq_used(pq q)
164 return q->used;