mirror of
https://github.com/git-for-windows/git.git
synced 2026-06-15 18:49:48 -05:00
Merge branch 'kk/prio-queue-get-put-fusion' into seen
The lazy priority queue optimization pattern (deferring actual removal in prio_queue_get() to allow get+put fusion) has been folded directly into prio_queue itself, speeding up commit traversal workflows and simplifying callers. * kk/prio-queue-get-put-fusion: prio-queue: fold lazy_queue into prio_queue for automatic get+put fusion prio-queue: rename .nr to .nr_ and add accessor helpers
This commit is contained in:
@@ -251,56 +251,19 @@ static int compare_pt(const void *a_, const void *b_)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct lazy_queue {
|
||||
struct prio_queue queue;
|
||||
bool get_pending;
|
||||
};
|
||||
|
||||
#define LAZY_QUEUE_INIT { { compare_commits_by_commit_date }, false }
|
||||
|
||||
static void *lazy_queue_get(struct lazy_queue *queue)
|
||||
{
|
||||
if (queue->get_pending)
|
||||
prio_queue_get(&queue->queue);
|
||||
else
|
||||
queue->get_pending = true;
|
||||
return prio_queue_peek(&queue->queue);
|
||||
}
|
||||
|
||||
static void lazy_queue_put(struct lazy_queue *queue, void *thing)
|
||||
{
|
||||
if (queue->get_pending)
|
||||
prio_queue_replace(&queue->queue, thing);
|
||||
else
|
||||
prio_queue_put(&queue->queue, thing);
|
||||
queue->get_pending = false;
|
||||
}
|
||||
|
||||
static bool lazy_queue_empty(const struct lazy_queue *queue)
|
||||
{
|
||||
return queue->queue.nr == (queue->get_pending ? 1 : 0);
|
||||
}
|
||||
|
||||
static void lazy_queue_clear(struct lazy_queue *queue)
|
||||
{
|
||||
clear_prio_queue(&queue->queue);
|
||||
queue->get_pending = false;
|
||||
}
|
||||
|
||||
static unsigned long finish_depth_computation(struct lazy_queue *queue,
|
||||
static unsigned long finish_depth_computation(struct prio_queue *queue,
|
||||
struct possible_tag *best)
|
||||
{
|
||||
unsigned long seen_commits = 0;
|
||||
struct oidset unflagged = OIDSET_INIT;
|
||||
struct commit *c;
|
||||
|
||||
for (size_t i = queue->get_pending ? 1 : 0; i < queue->queue.nr; i++) {
|
||||
struct commit *commit = queue->queue.array[i].data;
|
||||
if (!(commit->object.flags & best->flag_within))
|
||||
oidset_insert(&unflagged, &commit->object.oid);
|
||||
prio_queue_for_each(queue, c) {
|
||||
if (!(c->object.flags & best->flag_within))
|
||||
oidset_insert(&unflagged, &c->object.oid);
|
||||
}
|
||||
|
||||
while (!lazy_queue_empty(queue)) {
|
||||
struct commit *c = lazy_queue_get(queue);
|
||||
while ((c = prio_queue_get(queue))) {
|
||||
struct commit_list *parents = c->parents;
|
||||
seen_commits++;
|
||||
if (c->object.flags & best->flag_within) {
|
||||
@@ -316,7 +279,7 @@ static unsigned long finish_depth_computation(struct lazy_queue *queue,
|
||||
repo_parse_commit(the_repository, p);
|
||||
seen = p->object.flags & SEEN;
|
||||
if (!seen)
|
||||
lazy_queue_put(queue, p);
|
||||
prio_queue_put(queue, p);
|
||||
flag_before = p->object.flags & best->flag_within;
|
||||
p->object.flags |= c->object.flags;
|
||||
flag_after = p->object.flags & best->flag_within;
|
||||
@@ -364,8 +327,8 @@ static void append_suffix(int depth, const struct object_id *oid, struct strbuf
|
||||
|
||||
static void describe_commit(struct commit *cmit, struct strbuf *dst)
|
||||
{
|
||||
struct commit *gave_up_on = NULL;
|
||||
struct lazy_queue queue = LAZY_QUEUE_INIT;
|
||||
struct commit *c, *gave_up_on = NULL;
|
||||
struct prio_queue queue = { compare_commits_by_commit_date };
|
||||
struct commit_name *n;
|
||||
struct possible_tag all_matches[MAX_TAGS];
|
||||
unsigned int match_cnt = 0, annotated_cnt = 0, cur_match;
|
||||
@@ -407,9 +370,8 @@ static void describe_commit(struct commit *cmit, struct strbuf *dst)
|
||||
}
|
||||
|
||||
cmit->object.flags = SEEN;
|
||||
lazy_queue_put(&queue, cmit);
|
||||
while (!lazy_queue_empty(&queue)) {
|
||||
struct commit *c = lazy_queue_get(&queue);
|
||||
prio_queue_put(&queue, cmit);
|
||||
while ((c = prio_queue_get(&queue))) {
|
||||
struct commit_list *parents = c->parents;
|
||||
struct commit_name **slot;
|
||||
|
||||
@@ -443,7 +405,7 @@ static void describe_commit(struct commit *cmit, struct strbuf *dst)
|
||||
t->depth++;
|
||||
}
|
||||
/* Stop if last remaining path already covered by best candidate(s) */
|
||||
if (annotated_cnt && lazy_queue_empty(&queue)) {
|
||||
if (annotated_cnt && !prio_queue_size(&queue)) {
|
||||
int best_depth = INT_MAX;
|
||||
unsigned best_within = 0;
|
||||
for (cur_match = 0; cur_match < match_cnt; cur_match++) {
|
||||
@@ -466,7 +428,7 @@ static void describe_commit(struct commit *cmit, struct strbuf *dst)
|
||||
struct commit *p = parents->item;
|
||||
repo_parse_commit(the_repository, p);
|
||||
if (!(p->object.flags & SEEN))
|
||||
lazy_queue_put(&queue, p);
|
||||
prio_queue_put(&queue, p);
|
||||
p->object.flags |= c->object.flags;
|
||||
parents = parents->next;
|
||||
|
||||
@@ -481,7 +443,7 @@ static void describe_commit(struct commit *cmit, struct strbuf *dst)
|
||||
strbuf_add_unique_abbrev(dst, cmit_oid, abbrev);
|
||||
if (suffix)
|
||||
strbuf_addstr(dst, suffix);
|
||||
lazy_queue_clear(&queue);
|
||||
clear_prio_queue(&queue);
|
||||
return;
|
||||
}
|
||||
if (unannotated_cnt)
|
||||
@@ -497,11 +459,11 @@ static void describe_commit(struct commit *cmit, struct strbuf *dst)
|
||||
QSORT(all_matches, match_cnt, compare_pt);
|
||||
|
||||
if (gave_up_on) {
|
||||
lazy_queue_put(&queue, gave_up_on);
|
||||
prio_queue_put(&queue, gave_up_on);
|
||||
seen_commits--;
|
||||
}
|
||||
seen_commits += finish_depth_computation(&queue, &all_matches[0]);
|
||||
lazy_queue_clear(&queue);
|
||||
clear_prio_queue(&queue);
|
||||
|
||||
if (debug) {
|
||||
static int label_width = -1;
|
||||
|
||||
@@ -344,6 +344,7 @@ static void process_parent(struct last_modified *lm,
|
||||
static int last_modified_run(struct last_modified *lm)
|
||||
{
|
||||
int max_count, queue_popped = 0;
|
||||
struct commit *c, *n;
|
||||
struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
|
||||
struct prio_queue not_queue = { compare_commits_by_gen_then_commit_date };
|
||||
struct commit_list *list;
|
||||
@@ -389,10 +390,9 @@ static int last_modified_run(struct last_modified *lm)
|
||||
}
|
||||
}
|
||||
|
||||
while (queue.nr) {
|
||||
while ((c = prio_queue_get(&queue))) {
|
||||
int parent_i;
|
||||
struct commit_list *p;
|
||||
struct commit *c = prio_queue_get(&queue);
|
||||
struct bitmap *active_c = active_paths_for(lm, c);
|
||||
|
||||
if ((0 <= max_count && max_count < ++queue_popped) ||
|
||||
@@ -416,9 +416,8 @@ static int last_modified_run(struct last_modified *lm)
|
||||
*/
|
||||
repo_parse_commit(lm->rev.repo, c);
|
||||
|
||||
while (not_queue.nr) {
|
||||
while ((n = prio_queue_get(¬_queue))) {
|
||||
struct commit_list *np;
|
||||
struct commit *n = prio_queue_get(¬_queue);
|
||||
|
||||
repo_parse_commit(lm->rev.repo, n);
|
||||
|
||||
|
||||
@@ -62,11 +62,10 @@ static const char *get_color_reset_code(void)
|
||||
|
||||
static struct commit *interesting(struct prio_queue *queue)
|
||||
{
|
||||
for (size_t i = 0; i < queue->nr; i++) {
|
||||
struct commit *commit = queue->array[i].data;
|
||||
if (commit->object.flags & UNINTERESTING)
|
||||
continue;
|
||||
return commit;
|
||||
struct commit *commit;
|
||||
prio_queue_for_each(queue, commit) {
|
||||
if (!(commit->object.flags & UNINTERESTING))
|
||||
return commit;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -228,17 +227,18 @@ static void join_revs(struct prio_queue *queue,
|
||||
{
|
||||
int all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
|
||||
int all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
|
||||
struct commit *commit;
|
||||
|
||||
while (queue->nr) {
|
||||
while ((commit = prio_queue_peek(queue))) {
|
||||
struct commit_list *parents;
|
||||
int still_interesting = !!interesting(queue);
|
||||
struct commit *commit = prio_queue_peek(queue);
|
||||
bool get_pending = true;
|
||||
int flags = commit->object.flags & all_mask;
|
||||
|
||||
if (!still_interesting && extra <= 0)
|
||||
break;
|
||||
|
||||
prio_queue_get(queue);
|
||||
|
||||
mark_seen(commit, seen_p);
|
||||
if ((flags & all_revs) == all_revs)
|
||||
flags |= UNINTERESTING;
|
||||
@@ -254,14 +254,8 @@ static void join_revs(struct prio_queue *queue,
|
||||
if (mark_seen(p, seen_p) && !still_interesting)
|
||||
extra--;
|
||||
p->object.flags |= flags;
|
||||
if (get_pending)
|
||||
prio_queue_replace(queue, p);
|
||||
else
|
||||
prio_queue_put(queue, p);
|
||||
get_pending = false;
|
||||
prio_queue_put(queue, p);
|
||||
}
|
||||
if (get_pending)
|
||||
prio_queue_get(queue);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1121,6 +1121,7 @@ void ahead_behind(struct repository *r,
|
||||
struct nonstale_queue queue = {
|
||||
{ .compare = compare_commits_by_gen_then_commit_date }
|
||||
};
|
||||
void *entry;
|
||||
size_t width = DIV_ROUND_UP(commits_nr, BITS_IN_EWORD);
|
||||
|
||||
if (!commits_nr || !counts_nr)
|
||||
@@ -1186,8 +1187,8 @@ void ahead_behind(struct repository *r,
|
||||
|
||||
/* STALE is used here, PARENT2 is used by insert_no_dup(). */
|
||||
repo_clear_commit_marks(r, PARENT2 | STALE);
|
||||
for (size_t i = 0; i < queue.pq.nr; i++)
|
||||
free_bit_array(queue.pq.array[i].data);
|
||||
prio_queue_for_each(&queue.pq, entry)
|
||||
free_bit_array(entry);
|
||||
clear_bit_arrays(&bit_arrays);
|
||||
clear_nonstale_queue(&queue);
|
||||
}
|
||||
@@ -1320,7 +1321,7 @@ int get_branch_base_for_tip(struct repository *r,
|
||||
size_t bases_nr)
|
||||
{
|
||||
int best_index = -1;
|
||||
struct commit *branch_point = NULL;
|
||||
struct commit *c, *branch_point = NULL;
|
||||
struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
|
||||
int found_missing_gen = 0;
|
||||
|
||||
@@ -1373,8 +1374,7 @@ int get_branch_base_for_tip(struct repository *r,
|
||||
prio_queue_put(&queue, c);
|
||||
}
|
||||
|
||||
while (queue.nr) {
|
||||
struct commit *c = prio_queue_get(&queue);
|
||||
while ((c = prio_queue_get(&queue))) {
|
||||
int best_for_c = get_best(c);
|
||||
int best_for_p, positive;
|
||||
struct commit *parent;
|
||||
|
||||
11
commit.c
11
commit.c
@@ -782,24 +782,17 @@ void commit_list_sort_by_date(struct commit_list **list)
|
||||
struct commit *pop_most_recent_commit(struct prio_queue *queue,
|
||||
unsigned int mark)
|
||||
{
|
||||
struct commit *ret = prio_queue_peek(queue);
|
||||
int get_pending = 1;
|
||||
struct commit *ret = prio_queue_get(queue);
|
||||
struct commit_list *parents = ret->parents;
|
||||
|
||||
while (parents) {
|
||||
struct commit *commit = parents->item;
|
||||
if (!repo_parse_commit(the_repository, commit) && !(commit->object.flags & mark)) {
|
||||
commit->object.flags |= mark;
|
||||
if (get_pending)
|
||||
prio_queue_replace(queue, commit);
|
||||
else
|
||||
prio_queue_put(queue, commit);
|
||||
get_pending = 0;
|
||||
prio_queue_put(queue, commit);
|
||||
}
|
||||
parents = parents->next;
|
||||
}
|
||||
if (get_pending)
|
||||
prio_queue_get(queue);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -662,8 +662,8 @@ static int mark_complete_oid(const struct reference *ref, void *cb_data UNUSED)
|
||||
static void mark_recent_complete_commits(struct fetch_pack_args *args,
|
||||
timestamp_t cutoff)
|
||||
{
|
||||
while (complete.nr) {
|
||||
struct commit *item = prio_queue_peek(&complete);
|
||||
struct commit *item;
|
||||
while ((item = prio_queue_peek(&complete))) {
|
||||
if (item->date < cutoff)
|
||||
break;
|
||||
print_verbose(args, _("Marking %s as complete"),
|
||||
|
||||
@@ -113,10 +113,12 @@ static const struct object_id *get_rev(struct negotiation_state *ns)
|
||||
unsigned int mark;
|
||||
struct commit_list *parents;
|
||||
|
||||
if (ns->rev_list.nr == 0 || ns->non_common_revs == 0)
|
||||
if (ns->non_common_revs == 0)
|
||||
return NULL;
|
||||
|
||||
commit = prio_queue_get(&ns->rev_list);
|
||||
if (!commit)
|
||||
return NULL;
|
||||
repo_parse_commit(the_repository, commit);
|
||||
parents = commit->parents;
|
||||
|
||||
|
||||
@@ -143,8 +143,7 @@ static int push_parent(struct data *data, struct entry *entry,
|
||||
/*
|
||||
* Find the existing entry and use it.
|
||||
*/
|
||||
for (size_t i = 0; i < data->rev_list.nr; i++) {
|
||||
parent_entry = data->rev_list.array[i].data;
|
||||
prio_queue_for_each(&data->rev_list, parent_entry) {
|
||||
if (parent_entry->commit == to_push)
|
||||
goto parent_found;
|
||||
}
|
||||
@@ -181,10 +180,12 @@ static const struct object_id *get_rev(struct data *data)
|
||||
struct commit_list *p;
|
||||
int parent_pushed = 0;
|
||||
|
||||
if (data->rev_list.nr == 0 || data->non_common_revs == 0)
|
||||
if (data->non_common_revs == 0)
|
||||
return NULL;
|
||||
|
||||
entry = prio_queue_get(&data->rev_list);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
commit = entry->commit;
|
||||
commit->object.flags |= POPPED;
|
||||
if (!(commit->object.flags & COMMON))
|
||||
@@ -253,8 +254,9 @@ static void have_sent(struct fetch_negotiator *n, struct commit *c)
|
||||
static void release(struct fetch_negotiator *n)
|
||||
{
|
||||
struct data *data = n->data;
|
||||
for (size_t i = 0; i < data->rev_list.nr; i++)
|
||||
free(data->rev_list.array[i].data);
|
||||
void *entry;
|
||||
prio_queue_for_each(&data->rev_list, entry)
|
||||
free(entry);
|
||||
clear_prio_queue(&data->rev_list);
|
||||
FREE_AND_NULL(data);
|
||||
}
|
||||
|
||||
@@ -1209,7 +1209,7 @@ static int get_oid_oneline(struct repository *r,
|
||||
l->item->object.flags |= ONELINE_SEEN;
|
||||
prio_queue_put(©, l->item);
|
||||
}
|
||||
while (copy.nr) {
|
||||
while (prio_queue_size(©)) {
|
||||
const char *p, *buf;
|
||||
struct commit *commit;
|
||||
int matches;
|
||||
|
||||
@@ -636,6 +636,8 @@ static int fill_bitmap_commit(struct bitmap_writer *writer,
|
||||
struct bitmap_index *old_bitmap,
|
||||
const uint32_t *mapping)
|
||||
{
|
||||
struct commit *c;
|
||||
struct tree *t;
|
||||
int found;
|
||||
int from_pseudo_merge = commit->object.flags & BITMAP_PSEUDO_MERGE;
|
||||
uint32_t pos;
|
||||
@@ -650,9 +652,8 @@ static int fill_bitmap_commit(struct bitmap_writer *writer,
|
||||
|
||||
prio_queue_put(queue, commit);
|
||||
|
||||
while (queue->nr) {
|
||||
while ((c = prio_queue_get(queue))) {
|
||||
struct commit_list *p;
|
||||
struct commit *c = prio_queue_get(queue);
|
||||
|
||||
if (old_bitmap && mapping) {
|
||||
struct ewah_bitmap *old;
|
||||
@@ -740,8 +741,7 @@ static int fill_bitmap_commit(struct bitmap_writer *writer,
|
||||
}
|
||||
}
|
||||
|
||||
while (tree_queue->nr) {
|
||||
struct tree *t = prio_queue_get(tree_queue);
|
||||
while ((t = prio_queue_get(tree_queue))) {
|
||||
int found;
|
||||
|
||||
pos = find_object_pos(writer, &t->object.oid, &found);
|
||||
|
||||
@@ -699,6 +699,7 @@ int walk_objects_by_path(struct path_walk_info *info)
|
||||
int ret;
|
||||
size_t commits_nr = 0, paths_nr = 0;
|
||||
struct commit *c;
|
||||
char *path;
|
||||
struct type_and_oid_list *root_tree_list;
|
||||
struct type_and_oid_list *commit_list;
|
||||
struct path_walk_context ctx = {
|
||||
@@ -808,8 +809,7 @@ int walk_objects_by_path(struct path_walk_info *info)
|
||||
free(commit_list);
|
||||
|
||||
trace2_region_enter("path-walk", "path-walk", info->revs->repo);
|
||||
while (!ret && ctx.path_stack.nr) {
|
||||
char *path = prio_queue_get(&ctx.path_stack);
|
||||
while (!ret && (path = prio_queue_get(&ctx.path_stack))) {
|
||||
paths_nr++;
|
||||
|
||||
ret = walk_path(&ctx, path);
|
||||
@@ -821,12 +821,12 @@ int walk_objects_by_path(struct path_walk_info *info)
|
||||
if (!strmap_empty(&ctx.paths_to_lists)) {
|
||||
struct hashmap_iter iter;
|
||||
struct strmap_entry *entry;
|
||||
char *path;
|
||||
|
||||
strmap_for_each_entry(&ctx.paths_to_lists, &iter, entry)
|
||||
push_to_stack(&ctx, entry->key);
|
||||
|
||||
while (!ret && ctx.path_stack.nr) {
|
||||
char *path = prio_queue_get(&ctx.path_stack);
|
||||
while (!ret && (path = prio_queue_get(&ctx.path_stack))) {
|
||||
paths_nr++;
|
||||
|
||||
ret = walk_path(&ctx, path);
|
||||
|
||||
116
prio-queue.c
116
prio-queue.c
@@ -22,40 +22,19 @@ void prio_queue_reverse(struct prio_queue *queue)
|
||||
|
||||
if (queue->compare)
|
||||
BUG("prio_queue_reverse() on non-LIFO queue");
|
||||
if (!queue->nr)
|
||||
if (!queue->nr_)
|
||||
return;
|
||||
for (i = 0; i < (j = (queue->nr - 1) - i); i++)
|
||||
for (i = 0; i < (j = (queue->nr_ - 1) - i); i++)
|
||||
swap(queue, i, j);
|
||||
}
|
||||
|
||||
void clear_prio_queue(struct prio_queue *queue)
|
||||
{
|
||||
FREE_AND_NULL(queue->array);
|
||||
queue->nr = 0;
|
||||
queue->nr_ = 0;
|
||||
queue->alloc = 0;
|
||||
queue->insertion_ctr = 0;
|
||||
}
|
||||
|
||||
void prio_queue_put(struct prio_queue *queue, void *thing)
|
||||
{
|
||||
size_t ix, parent;
|
||||
|
||||
/* Append at the end */
|
||||
ALLOC_GROW(queue->array, queue->nr + 1, queue->alloc);
|
||||
queue->array[queue->nr].ctr = queue->insertion_ctr++;
|
||||
queue->array[queue->nr].data = thing;
|
||||
queue->nr++;
|
||||
if (!queue->compare)
|
||||
return; /* LIFO */
|
||||
|
||||
/* Bubble up the new one */
|
||||
for (ix = queue->nr - 1; ix; ix = parent) {
|
||||
parent = (ix - 1) / 2;
|
||||
if (compare(queue, parent, ix) <= 0)
|
||||
break;
|
||||
|
||||
swap(queue, parent, ix);
|
||||
}
|
||||
queue->get_pending = 0;
|
||||
}
|
||||
|
||||
static void sift_down_root(struct prio_queue *queue)
|
||||
@@ -63,9 +42,9 @@ static void sift_down_root(struct prio_queue *queue)
|
||||
size_t ix, child;
|
||||
|
||||
/* Push down the one at the root */
|
||||
for (ix = 0; ix * 2 + 1 < queue->nr; ix = child) {
|
||||
for (ix = 0; ix * 2 + 1 < queue->nr_; ix = child) {
|
||||
child = ix * 2 + 1; /* left */
|
||||
if (child + 1 < queue->nr &&
|
||||
if (child + 1 < queue->nr_ &&
|
||||
compare(queue, child, child + 1) >= 0)
|
||||
child++; /* use right child */
|
||||
|
||||
@@ -76,65 +55,72 @@ static void sift_down_root(struct prio_queue *queue)
|
||||
}
|
||||
}
|
||||
|
||||
static void sift_up_rebalance(struct prio_queue *queue)
|
||||
static inline void flush_get(struct prio_queue *queue)
|
||||
{
|
||||
size_t ix, child;
|
||||
if (!queue->get_pending)
|
||||
return;
|
||||
queue->get_pending = 0;
|
||||
queue->array[0] = queue->array[--queue->nr_];
|
||||
sift_down_root(queue);
|
||||
}
|
||||
|
||||
/* Cascade: promote smaller child at each level. */
|
||||
for (ix = 0; (child = ix * 2 + 1) < queue->nr; ix = child) {
|
||||
if (child + 1 < queue->nr &&
|
||||
compare(queue, child, child + 1) >= 0)
|
||||
child++;
|
||||
queue->array[ix] = queue->array[child];
|
||||
void prio_queue_put(struct prio_queue *queue, void *thing)
|
||||
{
|
||||
size_t ix, parent;
|
||||
|
||||
if (queue->get_pending) {
|
||||
queue->get_pending = 0;
|
||||
queue->array[0].ctr = queue->insertion_ctr++;
|
||||
queue->array[0].data = thing;
|
||||
sift_down_root(queue);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Place the last element at the vacancy and sift up. */
|
||||
queue->array[ix] = queue->array[queue->nr];
|
||||
while (ix) {
|
||||
size_t parent = (ix - 1) / 2;
|
||||
/* Append at the end */
|
||||
ALLOC_GROW(queue->array, queue->nr_ + 1, queue->alloc);
|
||||
queue->array[queue->nr_].ctr = queue->insertion_ctr++;
|
||||
queue->array[queue->nr_].data = thing;
|
||||
queue->nr_++;
|
||||
if (!queue->compare)
|
||||
return; /* LIFO */
|
||||
|
||||
/* Bubble up the new one */
|
||||
for (ix = queue->nr_ - 1; ix; ix = parent) {
|
||||
parent = (ix - 1) / 2;
|
||||
if (compare(queue, parent, ix) <= 0)
|
||||
break;
|
||||
|
||||
swap(queue, parent, ix);
|
||||
ix = parent;
|
||||
}
|
||||
}
|
||||
|
||||
void *prio_queue_get(struct prio_queue *queue)
|
||||
{
|
||||
void *result;
|
||||
|
||||
if (!queue->nr)
|
||||
if (queue->nr_ <= queue->get_pending) {
|
||||
queue->nr_ = 0;
|
||||
queue->get_pending = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (!queue->compare)
|
||||
return queue->array[--queue->nr].data; /* LIFO */
|
||||
return queue->array[--queue->nr_].data; /* LIFO */
|
||||
|
||||
result = queue->array[0].data;
|
||||
if (!--queue->nr)
|
||||
return result;
|
||||
flush_get(queue);
|
||||
|
||||
sift_up_rebalance(queue);
|
||||
return result;
|
||||
queue->get_pending = 1;
|
||||
return queue->array[0].data;
|
||||
}
|
||||
|
||||
void *prio_queue_peek(struct prio_queue *queue)
|
||||
{
|
||||
if (!queue->nr)
|
||||
if (queue->nr_ <= queue->get_pending) {
|
||||
queue->nr_ = 0;
|
||||
queue->get_pending = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (!queue->compare)
|
||||
return queue->array[queue->nr - 1].data;
|
||||
return queue->array[queue->nr_ - 1].data;
|
||||
|
||||
flush_get(queue);
|
||||
|
||||
return queue->array[0].data;
|
||||
}
|
||||
|
||||
void prio_queue_replace(struct prio_queue *queue, void *thing)
|
||||
{
|
||||
if (!queue->nr) {
|
||||
prio_queue_put(queue, thing);
|
||||
} else if (!queue->compare) {
|
||||
queue->array[queue->nr - 1].ctr = queue->insertion_ctr++;
|
||||
queue->array[queue->nr - 1].data = thing;
|
||||
} else {
|
||||
queue->array[0].ctr = queue->insertion_ctr++;
|
||||
queue->array[0].data = thing;
|
||||
sift_down_root(queue);
|
||||
}
|
||||
}
|
||||
|
||||
19
prio-queue.h
19
prio-queue.h
@@ -30,8 +30,9 @@ struct prio_queue {
|
||||
prio_queue_compare_fn compare;
|
||||
size_t insertion_ctr;
|
||||
void *cb_data;
|
||||
size_t alloc, nr;
|
||||
size_t alloc, nr_; /* use prio_queue_size() for logical count */
|
||||
struct prio_queue_entry *array;
|
||||
unsigned get_pending;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -52,13 +53,15 @@ void *prio_queue_get(struct prio_queue *);
|
||||
*/
|
||||
void *prio_queue_peek(struct prio_queue *);
|
||||
|
||||
/*
|
||||
* Replace the "thing" that compares the smallest with a new "thing",
|
||||
* like prio_queue_get()+prio_queue_put() would do, but in a more
|
||||
* efficient way. Does the same as prio_queue_put() if the queue is
|
||||
* empty.
|
||||
*/
|
||||
void prio_queue_replace(struct prio_queue *queue, void *thing);
|
||||
static inline size_t prio_queue_size(const struct prio_queue *queue)
|
||||
{
|
||||
return queue->nr_ - queue->get_pending;
|
||||
}
|
||||
|
||||
#define prio_queue_for_each(queue, it) \
|
||||
for (size_t pq_ix_ = (queue)->get_pending; \
|
||||
pq_ix_ < (queue)->nr_ && ((it) = (queue)->array[pq_ix_].data, 1); \
|
||||
pq_ix_++)
|
||||
|
||||
void clear_prio_queue(struct prio_queue *);
|
||||
|
||||
|
||||
17
revision.c
17
revision.c
@@ -476,16 +476,15 @@ static struct commit *handle_commit(struct rev_info *revs,
|
||||
static int everybody_uninteresting(struct prio_queue *orig,
|
||||
struct commit **interesting_cache)
|
||||
{
|
||||
size_t i;
|
||||
struct commit *commit;
|
||||
|
||||
if (*interesting_cache) {
|
||||
struct commit *commit = *interesting_cache;
|
||||
commit = *interesting_cache;
|
||||
if (!(commit->object.flags & UNINTERESTING))
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < orig->nr; i++) {
|
||||
struct commit *commit = orig->array[i].data;
|
||||
prio_queue_for_each(orig, commit) {
|
||||
if (commit->object.flags & UNINTERESTING)
|
||||
continue;
|
||||
|
||||
@@ -1442,7 +1441,7 @@ static int limit_list(struct rev_info *revs)
|
||||
struct commit_list *original_list = revs->commits;
|
||||
struct commit_list *newlist = NULL;
|
||||
struct commit_list **p = &newlist;
|
||||
struct commit *interesting_cache = NULL;
|
||||
struct commit *commit, *interesting_cache = NULL;
|
||||
struct prio_queue queue = { .compare = compare_commits_by_commit_date };
|
||||
|
||||
if (revs->ancestry_path_implicit_bottoms) {
|
||||
@@ -1457,8 +1456,7 @@ static int limit_list(struct rev_info *revs)
|
||||
prio_queue_put(&queue, commit);
|
||||
}
|
||||
|
||||
while (queue.nr) {
|
||||
struct commit *commit = prio_queue_get(&queue);
|
||||
while ((commit = prio_queue_get(&queue))) {
|
||||
struct object *obj = &commit->object;
|
||||
|
||||
if (commit == interesting_cache)
|
||||
@@ -4056,8 +4054,9 @@ static enum rewrite_result rewrite_one_1(struct rev_info *revs,
|
||||
static void merge_queue_into_prio_queue(struct prio_queue *from,
|
||||
struct prio_queue *to)
|
||||
{
|
||||
while (from->nr)
|
||||
prio_queue_put(to, prio_queue_get(from));
|
||||
struct commit *item;
|
||||
while ((item = prio_queue_get(from)))
|
||||
prio_queue_put(to, item);
|
||||
}
|
||||
|
||||
static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp)
|
||||
|
||||
@@ -53,13 +53,13 @@ static void test_prio_queue(int *input, size_t input_size,
|
||||
prio_queue_reverse(&pq);
|
||||
break;
|
||||
case REPLACE:
|
||||
peek = prio_queue_peek(&pq);
|
||||
get = prio_queue_get(&pq);
|
||||
cl_assert(i + 1 < input_size);
|
||||
cl_assert(input[i + 1] >= 0);
|
||||
cl_assert(j < result_size);
|
||||
cl_assert_equal_i(result[j], show(peek));
|
||||
cl_assert_equal_i(result[j], show(get));
|
||||
j++;
|
||||
prio_queue_replace(&pq, &input[++i]);
|
||||
prio_queue_put(&pq, &input[++i]);
|
||||
break;
|
||||
default:
|
||||
prio_queue_put(&pq, &input[i]);
|
||||
|
||||
4
walker.c
4
walker.c
@@ -84,12 +84,12 @@ static struct prio_queue complete = { compare_commits_by_commit_date };
|
||||
static int process_commit(struct walker *walker, struct commit *commit)
|
||||
{
|
||||
struct commit_list *parents;
|
||||
struct commit *item;
|
||||
|
||||
if (repo_parse_commit(the_repository, commit))
|
||||
return -1;
|
||||
|
||||
while (complete.nr) {
|
||||
struct commit *item = prio_queue_peek(&complete);
|
||||
while ((item = prio_queue_peek(&complete))) {
|
||||
if (item->date < commit->date)
|
||||
break;
|
||||
pop_most_recent_commit(&complete, COMPLETE);
|
||||
|
||||
Reference in New Issue
Block a user