Re: [PATCH 15/16] commit-reach: make can_all_from_reach... linear
- From
Derrick Stolee <stolee@gmail.com>
- Date
- Oct 5, 2018, 12:15 UTC
- Message-ID
- <f27fd384-6cfa-5acb-3e2b-72668f04d689@gmail.com>
- In-Reply-To
- <7b95417a-c8fb-4f1e-cb09-c36804a3a4d0@web.de>
On 10/4/2018 6:59 PM, René Scharfe wrote:
Show 13 quoted lines
> Am 01.10.2018 um 22:37 schrieb René Scharfe: >> Am 01.10.2018 um 21:26 schrieb Derrick Stolee: >>> Good catch! I'm disappointed that we couldn't use type-checking here, as >>> it is quite difficult to discover that the types are wrong here. >> Generics in C are hard, and type checking traditionally falls by the >> wayside. You could use macros for that, like klib [*] does, but that >> has its own downsides (more object text, debugging the sort macros >> themselves is harder). >> >> [*] https://github.com/attractivechaos/klib/blob/master/ksort.h > We could also do something like this to reduce the amount of manual > casting, but do we want to? (Macro at the bottom, three semi-random > examples at the top.)
I like the idea! It certainly can assist in some of the repeat work when preparing to QSORT, and make it less error-prone.
Show 89 quoted lines
> ---
> bisect.c | 11 +++--------
> commit-graph.c | 9 ++-------
> commit-reach.c | 12 +++++-------
> git-compat-util.h | 12 ++++++++++++
> 4 files changed, 22 insertions(+), 22 deletions(-)
>
> diff --git a/bisect.c b/bisect.c
> index e8b17cf7e1..06be3a3c15 100644
> --- a/bisect.c
> +++ b/bisect.c
> @@ -192,16 +192,11 @@ struct commit_dist {
> int distance;
> };
>
> -static int compare_commit_dist(const void *a_, const void *b_)
> -{
> - struct commit_dist *a, *b;
> -
> - a = (struct commit_dist *)a_;
> - b = (struct commit_dist *)b_;
> +DEFINE_SORT(sort_by_commit_dist, struct commit_dist, a, b, {
> if (a->distance != b->distance)
> return b->distance - a->distance; /* desc sort */
> return oidcmp(&a->commit->object.oid, &b->commit->object.oid);
> -}
> +})
>
> static struct commit_list *best_bisection_sorted(struct commit_list *list, int nr)
> {
> @@ -223,7 +218,7 @@ static struct commit_list *best_bisection_sorted(struct commit_list *list, int n
> array[cnt].distance = distance;
> cnt++;
> }
> - QSORT(array, cnt, compare_commit_dist);
> + sort_by_commit_dist(array, cnt);
> for (p = list, i = 0; i < cnt; i++) {
> struct object *obj = &(array[i].commit->object);
>
> diff --git a/commit-graph.c b/commit-graph.c
> index 7f4519ec3b..a2202414e0 100644
> --- a/commit-graph.c
> +++ b/commit-graph.c
> @@ -550,12 +550,7 @@ static void write_graph_chunk_large_edges(struct hashfile *f,
> }
> }
>
> -static int commit_compare(const void *_a, const void *_b)
> -{
> - const struct object_id *a = (const struct object_id *)_a;
> - const struct object_id *b = (const struct object_id *)_b;
> - return oidcmp(a, b);
> -}
> +DEFINE_SORT(sort_oids, struct object_id, a, b, return oidcmp(a, b))
>
> struct packed_commit_list {
> struct commit **list;
> @@ -780,7 +775,7 @@ void write_commit_graph(const char *obj_dir,
>
> close_reachable(&oids);
>
> - QSORT(oids.list, oids.nr, commit_compare);
> + sort_oids(oids.list, oids.nr);
>
> count_distinct = 1;
> for (i = 1; i < oids.nr; i++) {
> diff --git a/commit-reach.c b/commit-reach.c
> index 2f5e592d16..3aef47c3dd 100644
> --- a/commit-reach.c
> +++ b/commit-reach.c
> @@ -527,17 +527,15 @@ int commit_contains(struct ref_filter *filter, struct commit *commit,
> return is_descendant_of(commit, list);
> }
>
> -static int compare_commits_by_gen(const void *_a, const void *_b)
> -{
> - const struct commit *a = *(const struct commit * const *)_a;
> - const struct commit *b = *(const struct commit * const *)_b;
> -
> +DEFINE_SORT(sort_commits_by_gen, struct commit *, ap, bp, {
> + const struct commit *a = *ap;
> + const struct commit *b = *bp;
> if (a->generation < b->generation)
> return -1;
> if (a->generation > b->generation)
> return 1;
> return 0;
> -}
> +})Here, to make the macro version compile you need to cast ap and bp, which gives us a level of type-safety that wasn't there before. That can help us find errors at compile-time!
Show 32 quoted lines
>
> int can_all_from_reach_with_flag(struct object_array *from,
> unsigned int with_flag,
> @@ -580,7 +578,7 @@ int can_all_from_reach_with_flag(struct object_array *from,
> nr_commits++;
> }
>
> - QSORT(list, nr_commits, compare_commits_by_gen);
> + sort_commits_by_gen(list, nr_commits);
>
> for (i = 0; i < nr_commits; i++) {
> /* DFS from list[i] */
> diff --git a/git-compat-util.h b/git-compat-util.h
> index 5f2e90932f..f9e78d69a2 100644
> --- a/git-compat-util.h
> +++ b/git-compat-util.h
> @@ -1066,6 +1066,18 @@ static inline void sane_qsort(void *base, size_t nmemb, size_t size,
> qsort(base, nmemb, size, compar);
> }
>
> +#define DEFINE_SORT(name, elemtype, one, two, code) \
> +static int name##_compare(const void *one##_v_, const void *two##_v_) \
> +{ \
> + elemtype const *one = one##_v_; \
> + elemtype const *two = two##_v_; \
> + code; \
> +} \
> +static void name(elemtype *array, size_t n) \
> +{ \
> + QSORT(array, n, name##_compare); \
> +}
> +I would use this macro.
Thanks,
-Stolee