prio-queue: add 'peek' operation

When consuming a priority queue, it can be convenient to inspect the next object that will be dequeued without actually dequeueing it. Our existing library did not have such a 'peek' operation, so add it as prio_queue_peek(). Add a reference-level comparison in t/helper/test-prio-queue.c so this method is exercised by t0009-prio-queue.sh. Further, add a test that checks the behavior when the compare function is NULL (i.e. the queue becomes a stack). Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Nov 1, 2018 at 13:46 UTC aca4240f6a32423df5f95de6a9354b524fe57ec5
4 files changed +47 -8
prio-queue.c
+9
@@ -85,3 +85,12 @@ void *prio_queue_get(struct prio_queue *queue)
85 }
86 return result;
87 }
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 +}
prio-queue.h
+6
@@ -46,6 +46,12 @@ extern void prio_queue_put(struct prio_queue *, void *thing);
46 */
47 extern void *prio_queue_get(struct prio_queue *);
48
49 +/*
50 + * Gain access to the "thing" that would be returned by
51 + * prio_queue_get, but do not remove it from the queue.
52 + */
53 +extern void *prio_queue_peek(struct prio_queue *);
54 +
55 extern void clear_prio_queue(struct prio_queue *);
56
57 /* Reverse the LIFO elements */
t/helper/test-prio-queue.c
+18 -8
@@ -22,14 +22,24 @@ int cmd__prio_queue(int argc, const char **argv)
22 struct prio_queue pq = { intcmp };
23
24 while (*++argv) {
25 - if (!strcmp(*argv, "get"))
26 - show(prio_queue_get(&pq));
27 - else if (!strcmp(*argv, "dump")) {
28 - int *v;
29 - while ((v = prio_queue_get(&pq)))
30 - show(v);
31 - }
32 - else {
25 + if (!strcmp(*argv, "get")) {
26 + void *peek = prio_queue_peek(&pq);
27 + void *get = prio_queue_get(&pq);
28 + if (peek != get)
29 + BUG("peek and get results do not match");
30 + show(get);
31 + } else if (!strcmp(*argv, "dump")) {
32 + void *peek;
33 + void *get;
34 + while ((peek = prio_queue_peek(&pq))) {
35 + get = prio_queue_get(&pq);
36 + if (peek != get)
37 + BUG("peek and get results do not match");
38 + show(get);
39 + }
40 + } else if (!strcmp(*argv, "stack")) {
41 + pq.compare = NULL;
42 + } else {
43 int *v = malloc(sizeof(*v));
44 *v = atoi(*argv);
45 prio_queue_put(&pq, v);
t/t0009-prio-queue.sh
+14
@@ -47,4 +47,18 @@ test_expect_success 'notice empty queue' '
47 test_cmp expect actual
48 '
49
50 +cat >expect <<'EOF'
51 +3
52 +2
53 +6
54 +4
55 +5
56 +1
57 +8
58 +EOF
59 +test_expect_success 'stack order' '
60 + test-tool prio-queue stack 8 1 5 4 6 2 3 dump >actual &&
61 + test_cmp expect actual
62 +'
63 +
64 test_done