summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--commit-slab-decl.h1
-rw-r--r--commit-slab-impl.h13
-rw-r--r--commit-slab.h10
-rw-r--r--shallow.c14
4 files changed, 29 insertions, 9 deletions
diff --git a/commit-slab-decl.h b/commit-slab-decl.h
index adc7b46c83..286164b7e2 100644
--- a/commit-slab-decl.h
+++ b/commit-slab-decl.h
@@ -32,6 +32,7 @@ struct slabname { \
void init_ ##slabname## _with_stride(struct slabname *s, unsigned stride); \
void init_ ##slabname(struct slabname *s); \
void clear_ ##slabname(struct slabname *s); \
+void deep_clear_ ##slabname(struct slabname *s, void (*free_fn)(elemtype *ptr)); \
elemtype *slabname## _at_peek(struct slabname *s, const struct commit *c, int add_if_missing); \
elemtype *slabname## _at(struct slabname *s, const struct commit *c); \
elemtype *slabname## _peek(struct slabname *s, const struct commit *c)
diff --git a/commit-slab-impl.h b/commit-slab-impl.h
index 5c0eb91a5d..557738df27 100644
--- a/commit-slab-impl.h
+++ b/commit-slab-impl.h
@@ -38,6 +38,19 @@ scope void clear_ ##slabname(struct slabname *s) \
FREE_AND_NULL(s->slab); \
} \
\
+scope void deep_clear_ ##slabname(struct slabname *s, void (*free_fn)(elemtype *)) \
+{ \
+ unsigned int i; \
+ for (i = 0; i < s->slab_count; i++) { \
+ unsigned int j; \
+ if (!s->slab[i]) \
+ continue; \
+ for (j = 0; j < s->slab_size; j++) \
+ free_fn(&s->slab[i][j * s->stride]); \
+ } \
+ clear_ ##slabname(s); \
+} \
+ \
scope elemtype *slabname## _at_peek(struct slabname *s, \
const struct commit *c, \
int add_if_missing) \
diff --git a/commit-slab.h b/commit-slab.h
index 05b3f2804e..8e72a30536 100644
--- a/commit-slab.h
+++ b/commit-slab.h
@@ -47,6 +47,16 @@
*
* Call this function before the slab falls out of scope to avoid
* leaking memory.
+ *
+ * - void deep_clear_indegree(struct indegree *, void (*free_fn)(int*))
+ *
+ * Empties the slab, similar to clear_indegree(), but in addition it
+ * calls the given 'free_fn' for each slab entry to release any
+ * additional memory that might be owned by the entry (but not the
+ * entry itself!).
+ * Note that 'free_fn' might be called even for entries for which no
+ * indegree_at() call has been made; in this case 'free_fn' is invoked
+ * with a pointer to a zero-initialized location.
*/
#define define_commit_slab(slabname, elemtype) \
diff --git a/shallow.c b/shallow.c
index 7fd04afed1..c4ac8a7327 100644
--- a/shallow.c
+++ b/shallow.c
@@ -84,6 +84,10 @@ int is_repository_shallow(struct repository *r)
* supports a "valid" flag.
*/
define_commit_slab(commit_depth, int *);
+static void free_depth_in_slab(int **ptr)
+{
+ FREE_AND_NULL(*ptr);
+}
struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
int shallow_flag, int not_shallow_flag)
{
@@ -150,15 +154,7 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
}
}
}
- for (i = 0; i < depths.slab_count; i++) {
- int j;
-
- if (!depths.slab[i])
- continue;
- for (j = 0; j < depths.slab_size; j++)
- free(depths.slab[i][j]);
- }
- clear_commit_depth(&depths);
+ deep_clear_commit_depth(&depths, free_depth_in_slab);
return result;
}