Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 1 | #include "cache.h" |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 2 | #include "prio-queue.h" |
| 3 | |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 4 | static inline int compare(struct prio_queue *queue, int i, int j) |
| 5 | { |
Jeff King | e8f91e3 | 2014-07-14 01:51:59 -0400 | [diff] [blame] | 6 | int cmp = queue->compare(queue->array[i].data, queue->array[j].data, |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 7 | queue->cb_data); |
Jeff King | e8f91e3 | 2014-07-14 01:51:59 -0400 | [diff] [blame] | 8 | if (!cmp) |
| 9 | cmp = queue->array[i].ctr - queue->array[j].ctr; |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 10 | return cmp; |
| 11 | } |
| 12 | |
| 13 | static inline void swap(struct prio_queue *queue, int i, int j) |
| 14 | { |
René Scharfe | 35d803b | 2017-01-28 22:40:58 +0100 | [diff] [blame] | 15 | SWAP(queue->array[i], queue->array[j]); |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 16 | } |
| 17 | |
Junio C Hamano | da24b10 | 2013-06-06 21:58:12 -0700 | [diff] [blame] | 18 | void prio_queue_reverse(struct prio_queue *queue) |
| 19 | { |
| 20 | int i, j; |
| 21 | |
| 22 | if (queue->compare != NULL) |
Johannes Schindelin | 033abf9 | 2018-05-02 11:38:39 +0200 | [diff] [blame] | 23 | BUG("prio_queue_reverse() on non-LIFO queue"); |
Jeff King | 1f9e18b | 2017-04-24 07:49:20 -0400 | [diff] [blame] | 24 | for (i = 0; i < (j = (queue->nr - 1) - i); i++) |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 25 | swap(queue, i, j); |
Junio C Hamano | da24b10 | 2013-06-06 21:58:12 -0700 | [diff] [blame] | 26 | } |
| 27 | |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 28 | void clear_prio_queue(struct prio_queue *queue) |
| 29 | { |
Ævar Arnfjörð Bjarmason | 88ce3ef | 2017-06-15 23:15:49 +0000 | [diff] [blame] | 30 | FREE_AND_NULL(queue->array); |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 31 | queue->nr = 0; |
| 32 | queue->alloc = 0; |
Jeff King | e8f91e3 | 2014-07-14 01:51:59 -0400 | [diff] [blame] | 33 | queue->insertion_ctr = 0; |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 34 | } |
| 35 | |
| 36 | void prio_queue_put(struct prio_queue *queue, void *thing) |
| 37 | { |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 38 | int ix, parent; |
| 39 | |
| 40 | /* Append at the end */ |
| 41 | ALLOC_GROW(queue->array, queue->nr + 1, queue->alloc); |
Jeff King | e8f91e3 | 2014-07-14 01:51:59 -0400 | [diff] [blame] | 42 | queue->array[queue->nr].ctr = queue->insertion_ctr++; |
| 43 | queue->array[queue->nr].data = thing; |
| 44 | queue->nr++; |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 45 | if (!queue->compare) |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 46 | return; /* LIFO */ |
| 47 | |
| 48 | /* Bubble up the new one */ |
| 49 | for (ix = queue->nr - 1; ix; ix = parent) { |
| 50 | parent = (ix - 1) / 2; |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 51 | if (compare(queue, parent, ix) <= 0) |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 52 | break; |
| 53 | |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 54 | swap(queue, parent, ix); |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 55 | } |
| 56 | } |
| 57 | |
| 58 | void *prio_queue_get(struct prio_queue *queue) |
| 59 | { |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 60 | void *result; |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 61 | int ix, child; |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 62 | |
| 63 | if (!queue->nr) |
| 64 | return NULL; |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 65 | if (!queue->compare) |
Jeff King | e8f91e3 | 2014-07-14 01:51:59 -0400 | [diff] [blame] | 66 | return queue->array[--queue->nr].data; /* LIFO */ |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 67 | |
Jeff King | e8f91e3 | 2014-07-14 01:51:59 -0400 | [diff] [blame] | 68 | result = queue->array[0].data; |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 69 | if (!--queue->nr) |
| 70 | return result; |
| 71 | |
| 72 | queue->array[0] = queue->array[queue->nr]; |
| 73 | |
| 74 | /* Push down the one at the root */ |
| 75 | for (ix = 0; ix * 2 + 1 < queue->nr; ix = child) { |
| 76 | child = ix * 2 + 1; /* left */ |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 77 | if (child + 1 < queue->nr && |
| 78 | compare(queue, child, child + 1) >= 0) |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 79 | child++; /* use right child */ |
| 80 | |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 81 | if (compare(queue, ix, child) <= 0) |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 82 | break; |
| 83 | |
Jeff King | 6d63baa | 2014-07-14 01:42:50 -0400 | [diff] [blame] | 84 | swap(queue, child, ix); |
Junio C Hamano | b4b594a | 2013-06-06 19:13:50 -0700 | [diff] [blame] | 85 | } |
| 86 | return result; |
| 87 | } |
Derrick Stolee | aca4240 | 2018-11-01 13:46:17 +0000 | [diff] [blame] | 88 | |
| 89 | void *prio_queue_peek(struct prio_queue *queue) |
| 90 | { |
| 91 | if (!queue->nr) |
| 92 | return NULL; |
| 93 | if (!queue->compare) |
| 94 | return queue->array[queue->nr - 1].data; |
| 95 | return queue->array[0].data; |
| 96 | } |