зеркало из https://github.com/microsoft/git.git
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>
This commit is contained in:
Родитель
282616c72d
Коммит
862e730ec1
|
@ -15,7 +15,13 @@
|
|||
* - int *indegree_at(struct indegree *, struct commit *);
|
||||
*
|
||||
* This function locates the data associated with the given commit in
|
||||
* the indegree slab, and returns the pointer to it.
|
||||
* the indegree slab, and returns the pointer to it. The location to
|
||||
* store the data is allocated as necessary.
|
||||
*
|
||||
* - int *indegree_peek(struct indegree *, struct commit *);
|
||||
*
|
||||
* This function is similar to indegree_at(), but it will return NULL
|
||||
* until a call to indegree_at() was made for the commit.
|
||||
*
|
||||
* - void init_indegree(struct indegree *);
|
||||
* void init_indegree_with_stride(struct indegree *, int);
|
||||
|
@ -80,8 +86,9 @@ static MAYBE_UNUSED void clear_ ##slabname(struct slabname *s) \
|
|||
s->slab = NULL; \
|
||||
} \
|
||||
\
|
||||
static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \
|
||||
const struct commit *c) \
|
||||
static MAYBE_UNUSED elemtype *slabname## _at_peek(struct slabname *s, \
|
||||
const struct commit *c, \
|
||||
int add_if_missing) \
|
||||
{ \
|
||||
int nth_slab, nth_slot; \
|
||||
\
|
||||
|
@ -90,6 +97,8 @@ static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \
|
|||
\
|
||||
if (s->slab_count <= nth_slab) { \
|
||||
int i; \
|
||||
if (!add_if_missing) \
|
||||
return NULL; \
|
||||
s->slab = xrealloc(s->slab, \
|
||||
(nth_slab + 1) * sizeof(*s->slab)); \
|
||||
stat_ ##slabname## realloc++; \
|
||||
|
@ -97,10 +106,25 @@ static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \
|
|||
s->slab[i] = NULL; \
|
||||
s->slab_count = nth_slab + 1; \
|
||||
} \
|
||||
if (!s->slab[nth_slab]) \
|
||||
if (!s->slab[nth_slab]) { \
|
||||
if (!add_if_missing) \
|
||||
return NULL; \
|
||||
s->slab[nth_slab] = xcalloc(s->slab_size, \
|
||||
sizeof(**s->slab) * s->stride); \
|
||||
return &s->slab[nth_slab][nth_slot * s->stride]; \
|
||||
} \
|
||||
return &s->slab[nth_slab][nth_slot * s->stride]; \
|
||||
} \
|
||||
\
|
||||
static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \
|
||||
const struct commit *c) \
|
||||
{ \
|
||||
return slabname##_at_peek(s, c, 1); \
|
||||
} \
|
||||
\
|
||||
static MAYBE_UNUSED elemtype *slabname## _peek(struct slabname *s, \
|
||||
const struct commit *c) \
|
||||
{ \
|
||||
return slabname##_at_peek(s, c, 0); \
|
||||
} \
|
||||
\
|
||||
static int stat_ ##slabname## realloc
|
||||
|
|
28
commit.c
28
commit.c
|
@ -244,7 +244,12 @@ void set_commit_buffer(struct commit *commit, void *buffer, unsigned long size)
|
|||
|
||||
const void *get_cached_commit_buffer(const struct commit *commit, unsigned long *sizep)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
|
||||
if (!v) {
|
||||
if (sizep)
|
||||
*sizep = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (sizep)
|
||||
*sizep = v->size;
|
||||
return v->buffer;
|
||||
|
@ -271,24 +276,31 @@ const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep)
|
|||
|
||||
void unuse_commit_buffer(const struct commit *commit, const void *buffer)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
if (v->buffer != buffer)
|
||||
struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
|
||||
if (!(v && v->buffer == buffer))
|
||||
free((void *)buffer);
|
||||
}
|
||||
|
||||
void free_commit_buffer(struct commit *commit)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
free(v->buffer);
|
||||
v->buffer = NULL;
|
||||
v->size = 0;
|
||||
struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
|
||||
if (v) {
|
||||
free(v->buffer);
|
||||
v->buffer = NULL;
|
||||
v->size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const void *detach_commit_buffer(struct commit *commit, unsigned long *sizep)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit);
|
||||
void *ret;
|
||||
|
||||
if (!v) {
|
||||
if (sizep)
|
||||
*sizep = 0;
|
||||
return NULL;
|
||||
}
|
||||
ret = v->buffer;
|
||||
if (sizep)
|
||||
*sizep = v->size;
|
||||
|
|
Загрузка…
Ссылка в новой задаче