Skip to content

Commit 862e730

Browse files
committed
commit-slab: introduce slabname##_peek() function
There is no API to ask "Does this commit have associated data in slab?". If an application wants to (1) parse just a few commits at the beginning of a process, (2) store data for only these commits, and then (3) start processing many commits, taking into account the data stored (for a few of them) in the slab, the application would use slabname##_at() to allocate a space to store data in (2), but there is no API other than slabname##_at() to use in step (3). This allocates and wastes new space for these commits the caller is only interested in checking if they have data stored in step (2). Introduce slabname##_peek(), which is similar to slabname##_at() but returns NULL when there is no data already associated to it in such a use case. Helped-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 282616c commit 862e730

File tree

2 files changed

+49
-13
lines changed

2 files changed

+49
-13
lines changed

commit-slab.h

+29-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515
* - int *indegree_at(struct indegree *, struct commit *);
1616
*
1717
* This function locates the data associated with the given commit in
18-
* the indegree slab, and returns the pointer to it.
18+
* the indegree slab, and returns the pointer to it. The location to
19+
* store the data is allocated as necessary.
20+
*
21+
* - int *indegree_peek(struct indegree *, struct commit *);
22+
*
23+
* This function is similar to indegree_at(), but it will return NULL
24+
* until a call to indegree_at() was made for the commit.
1925
*
2026
* - void init_indegree(struct indegree *);
2127
* void init_indegree_with_stride(struct indegree *, int);
@@ -80,8 +86,9 @@ static MAYBE_UNUSED void clear_ ##slabname(struct slabname *s) \
8086
s->slab = NULL; \
8187
} \
8288
\
83-
static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \
84-
const struct commit *c) \
89+
static MAYBE_UNUSED elemtype *slabname## _at_peek(struct slabname *s, \
90+
const struct commit *c, \
91+
int add_if_missing) \
8592
{ \
8693
int nth_slab, nth_slot; \
8794
\
@@ -90,17 +97,34 @@ static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \
9097
\
9198
if (s->slab_count <= nth_slab) { \
9299
int i; \
100+
if (!add_if_missing) \
101+
return NULL; \
93102
s->slab = xrealloc(s->slab, \
94103
(nth_slab + 1) * sizeof(*s->slab)); \
95104
stat_ ##slabname## realloc++; \
96105
for (i = s->slab_count; i <= nth_slab; i++) \
97106
s->slab[i] = NULL; \
98107
s->slab_count = nth_slab + 1; \
99108
} \
100-
if (!s->slab[nth_slab]) \
109+
if (!s->slab[nth_slab]) { \
110+
if (!add_if_missing) \
111+
return NULL; \
101112
s->slab[nth_slab] = xcalloc(s->slab_size, \
102113
sizeof(**s->slab) * s->stride); \
103-
return &s->slab[nth_slab][nth_slot * s->stride]; \
114+
} \
115+
return &s->slab[nth_slab][nth_slot * s->stride]; \
116+
} \
117+
\
118+
static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \
119+
const struct commit *c) \
120+
{ \
121+
return slabname##_at_peek(s, c, 1); \
122+
} \
123+
\
124+
static MAYBE_UNUSED elemtype *slabname## _peek(struct slabname *s, \
125+
const struct commit *c) \
126+
{ \
127+
return slabname##_at_peek(s, c, 0); \
104128
} \
105129
\
106130
static int stat_ ##slabname## realloc

commit.c

+20-8
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,12 @@ void set_commit_buffer(struct commit *commit, void *buffer, unsigned long size)
244244

245245
const void *get_cached_commit_buffer(const struct commit *commit, unsigned long *sizep)
246246
{
247-
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
247+
struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
248+
if (!v) {
249+
if (sizep)
250+
*sizep = 0;
251+
return NULL;
252+
}
248253
if (sizep)
249254
*sizep = v->size;
250255
return v->buffer;
@@ -271,24 +276,31 @@ const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep)
271276

272277
void unuse_commit_buffer(const struct commit *commit, const void *buffer)
273278
{
274-
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
275-
if (v->buffer != buffer)
279+
struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
280+
if (!(v && v->buffer == buffer))
276281
free((void *)buffer);
277282
}
278283

279284
void free_commit_buffer(struct commit *commit)
280285
{
281-
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
282-
free(v->buffer);
283-
v->buffer = NULL;
284-
v->size = 0;
286+
struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
287+
if (v) {
288+
free(v->buffer);
289+
v->buffer = NULL;
290+
v->size = 0;
291+
}
285292
}
286293

287294
const void *detach_commit_buffer(struct commit *commit, unsigned long *sizep)
288295
{
289-
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
296+
struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
290297
void *ret;
291298

299+
if (!v) {
300+
if (sizep)
301+
*sizep = 0;
302+
return NULL;
303+
}
292304
ret = v->buffer;
293305
if (sizep)
294306
*sizep = v->size;

0 commit comments

Comments
 (0)