Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit 4799593

Browse files
committed
Merge branch 'jk/stable-prio-queue'
* jk/stable-prio-queue: t5539: update a flaky test paint_down_to_common: use prio_queue prio-queue: make output stable with respect to insertion prio-queue: factor out compare and swap operations
2 parents 996b0fd + f0e802c commit 4799593

File tree

4 files changed

+60
-51
lines changed

4 files changed

+60
-51
lines changed

commit.c

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -764,45 +764,41 @@ void sort_in_topological_order(struct commit_list **list, enum rev_sort_order so
764764

765765
static const unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT);
766766

767-
static struct commit *interesting(struct commit_list *list)
767+
static int queue_has_nonstale(struct prio_queue *queue)
768768
{
769-
while (list) {
770-
struct commit *commit = list->item;
771-
list = list->next;
772-
if (commit->object.flags & STALE)
773-
continue;
774-
return commit;
769+
int i;
770+
for (i = 0; i < queue->nr; i++) {
771+
struct commit *commit = queue->array[i].data;
772+
if (!(commit->object.flags & STALE))
773+
return 1;
775774
}
776-
return NULL;
775+
return 0;
777776
}
778777

779778
/* all input commits in one and twos[] must have been parsed! */
780779
static struct commit_list *paint_down_to_common(struct commit *one, int n, struct commit **twos)
781780
{
782-
struct commit_list *list = NULL;
781+
struct prio_queue queue = { compare_commits_by_commit_date };
783782
struct commit_list *result = NULL;
784783
int i;
785784

786785
one->object.flags |= PARENT1;
787-
commit_list_insert_by_date(one, &list);
788-
if (!n)
789-
return list;
786+
if (!n) {
787+
commit_list_append(one, &result);
788+
return result;
789+
}
790+
prio_queue_put(&queue, one);
791+
790792
for (i = 0; i < n; i++) {
791793
twos[i]->object.flags |= PARENT2;
792-
commit_list_insert_by_date(twos[i], &list);
794+
prio_queue_put(&queue, twos[i]);
793795
}
794796

795-
while (interesting(list)) {
796-
struct commit *commit;
797+
while (queue_has_nonstale(&queue)) {
798+
struct commit *commit = prio_queue_get(&queue);
797799
struct commit_list *parents;
798-
struct commit_list *next;
799800
int flags;
800801

801-
commit = list->item;
802-
next = list->next;
803-
free(list);
804-
list = next;
805-
806802
flags = commit->object.flags & (PARENT1 | PARENT2 | STALE);
807803
if (flags == (PARENT1 | PARENT2)) {
808804
if (!(commit->object.flags & RESULT)) {
@@ -821,11 +817,11 @@ static struct commit_list *paint_down_to_common(struct commit *one, int n, struc
821817
if (parse_commit(p))
822818
return NULL;
823819
p->object.flags |= flags;
824-
commit_list_insert_by_date(p, &list);
820+
prio_queue_put(&queue, p);
825821
}
826822
}
827823

828-
free_commit_list(list);
824+
clear_prio_queue(&queue);
829825
return result;
830826
}
831827

prio-queue.c

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
11
#include "cache.h"
2-
#include "commit.h"
32
#include "prio-queue.h"
43

4+
static inline int compare(struct prio_queue *queue, int i, int j)
5+
{
6+
int cmp = queue->compare(queue->array[i].data, queue->array[j].data,
7+
queue->cb_data);
8+
if (!cmp)
9+
cmp = queue->array[i].ctr - queue->array[j].ctr;
10+
return cmp;
11+
}
12+
13+
static inline void swap(struct prio_queue *queue, int i, int j)
14+
{
15+
struct prio_queue_entry tmp = queue->array[i];
16+
queue->array[i] = queue->array[j];
17+
queue->array[j] = tmp;
18+
}
19+
520
void prio_queue_reverse(struct prio_queue *queue)
621
{
722
int i, j;
823

924
if (queue->compare != NULL)
1025
die("BUG: prio_queue_reverse() on non-LIFO queue");
11-
for (i = 0; i <= (j = (queue->nr - 1) - i); i++) {
12-
struct commit *swap = queue->array[i];
13-
queue->array[i] = queue->array[j];
14-
queue->array[j] = swap;
15-
}
26+
for (i = 0; i <= (j = (queue->nr - 1) - i); i++)
27+
swap(queue, i, j);
1628
}
1729

1830
void clear_prio_queue(struct prio_queue *queue)
@@ -21,44 +33,42 @@ void clear_prio_queue(struct prio_queue *queue)
2133
queue->nr = 0;
2234
queue->alloc = 0;
2335
queue->array = NULL;
36+
queue->insertion_ctr = 0;
2437
}
2538

2639
void prio_queue_put(struct prio_queue *queue, void *thing)
2740
{
28-
prio_queue_compare_fn compare = queue->compare;
2941
int ix, parent;
3042

3143
/* Append at the end */
3244
ALLOC_GROW(queue->array, queue->nr + 1, queue->alloc);
33-
queue->array[queue->nr++] = thing;
34-
if (!compare)
45+
queue->array[queue->nr].ctr = queue->insertion_ctr++;
46+
queue->array[queue->nr].data = thing;
47+
queue->nr++;
48+
if (!queue->compare)
3549
return; /* LIFO */
3650

3751
/* Bubble up the new one */
3852
for (ix = queue->nr - 1; ix; ix = parent) {
3953
parent = (ix - 1) / 2;
40-
if (compare(queue->array[parent], queue->array[ix],
41-
queue->cb_data) <= 0)
54+
if (compare(queue, parent, ix) <= 0)
4255
break;
4356

44-
thing = queue->array[parent];
45-
queue->array[parent] = queue->array[ix];
46-
queue->array[ix] = thing;
57+
swap(queue, parent, ix);
4758
}
4859
}
4960

5061
void *prio_queue_get(struct prio_queue *queue)
5162
{
52-
void *result, *swap;
63+
void *result;
5364
int ix, child;
54-
prio_queue_compare_fn compare = queue->compare;
5565

5666
if (!queue->nr)
5767
return NULL;
58-
if (!compare)
59-
return queue->array[--queue->nr]; /* LIFO */
68+
if (!queue->compare)
69+
return queue->array[--queue->nr].data; /* LIFO */
6070

61-
result = queue->array[0];
71+
result = queue->array[0].data;
6272
if (!--queue->nr)
6373
return result;
6474

@@ -67,18 +77,14 @@ void *prio_queue_get(struct prio_queue *queue)
6777
/* Push down the one at the root */
6878
for (ix = 0; ix * 2 + 1 < queue->nr; ix = child) {
6979
child = ix * 2 + 1; /* left */
70-
if ((child + 1 < queue->nr) &&
71-
(compare(queue->array[child], queue->array[child + 1],
72-
queue->cb_data) >= 0))
80+
if (child + 1 < queue->nr &&
81+
compare(queue, child, child + 1) >= 0)
7382
child++; /* use right child */
7483

75-
if (compare(queue->array[ix], queue->array[child],
76-
queue->cb_data) <= 0)
84+
if (compare(queue, ix, child) <= 0)
7785
break;
7886

79-
swap = queue->array[child];
80-
queue->array[child] = queue->array[ix];
81-
queue->array[ix] = swap;
87+
swap(queue, child, ix);
8288
}
8389
return result;
8490
}

prio-queue.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,17 @@
2121
*/
2222
typedef int (*prio_queue_compare_fn)(const void *one, const void *two, void *cb_data);
2323

24+
struct prio_queue_entry {
25+
unsigned ctr;
26+
void *data;
27+
};
28+
2429
struct prio_queue {
2530
prio_queue_compare_fn compare;
31+
unsigned insertion_ctr;
2632
void *cb_data;
2733
int alloc, nr;
28-
void **array;
34+
struct prio_queue_entry *array;
2935
};
3036

3137
/*

t/t5539-fetch-http-shallow.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ EOF
5454
test_expect_success 'no shallow lines after receiving ACK ready' '
5555
(
5656
cd shallow &&
57+
test_tick &&
5758
for i in $(test_seq 15)
5859
do
5960
git checkout --orphan unrelated$i &&

0 commit comments

Comments
 (0)