commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
#ifndef COMMIT_SLAB_H
|
|
|
|
#define COMMIT_SLAB_H
|
|
|
|
|
|
|
|
/*
|
|
|
|
* define_commit_slab(slabname, elemtype) creates boilerplate code to define
|
|
|
|
* a new struct (struct slabname) that is used to associate a piece of data
|
|
|
|
* of elemtype to commits, and a few functions to use that struct.
|
|
|
|
*
|
|
|
|
* After including this header file, using:
|
|
|
|
*
|
|
|
|
* define_commit_slab(indegee, int);
|
|
|
|
*
|
|
|
|
* will let you call the following functions:
|
|
|
|
*
|
|
|
|
* - int *indegree_at(struct indegree *, struct commit *);
|
|
|
|
*
|
|
|
|
* This function locates the data associated with the given commit in
|
2015-05-15 06:25:52 +08:00
|
|
|
* 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.
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
*
|
|
|
|
* - void init_indegree(struct indegree *);
|
|
|
|
* void init_indegree_with_stride(struct indegree *, int);
|
|
|
|
*
|
|
|
|
* Initializes the indegree slab that associates an array of integers
|
|
|
|
* to each commit. 'stride' specifies how big each array is. The slab
|
2013-11-26 03:02:00 +08:00
|
|
|
* that is initialized by the variant without "_with_stride" associates
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
* each commit with an array of one integer.
|
2013-11-26 03:02:00 +08:00
|
|
|
*
|
|
|
|
* - void clear_indegree(struct indegree *);
|
|
|
|
*
|
|
|
|
* Empties the slab. The slab can be reused with the same stride
|
|
|
|
* without calling init_indegree() again or can be reconfigured to a
|
|
|
|
* different stride by calling init_indegree_with_stride().
|
|
|
|
*
|
|
|
|
* Call this function before the slab falls out of scope to avoid
|
|
|
|
* leaking memory.
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* allocate ~512kB at once, allowing for malloc overhead */
|
|
|
|
#ifndef COMMIT_SLAB_SIZE
|
|
|
|
#define COMMIT_SLAB_SIZE (512*1024-32)
|
|
|
|
#endif
|
|
|
|
|
2013-11-26 04:04:08 +08:00
|
|
|
#define MAYBE_UNUSED __attribute__((__unused__))
|
|
|
|
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
#define define_commit_slab(slabname, elemtype) \
|
|
|
|
\
|
|
|
|
struct slabname { \
|
|
|
|
unsigned slab_size; \
|
|
|
|
unsigned stride; \
|
|
|
|
unsigned slab_count; \
|
|
|
|
elemtype **slab; \
|
|
|
|
}; \
|
|
|
|
static int stat_ ##slabname## realloc; \
|
|
|
|
\
|
2013-11-26 04:04:08 +08:00
|
|
|
static MAYBE_UNUSED void init_ ##slabname## _with_stride(struct slabname *s, \
|
|
|
|
unsigned stride) \
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
{ \
|
|
|
|
unsigned int elem_size; \
|
|
|
|
if (!stride) \
|
|
|
|
stride = 1; \
|
|
|
|
s->stride = stride; \
|
commit-slab.h: Fix memory allocation and addressing
The slab initialization code includes the calculation of the
slab 'elem_size', which is in turn used to determine the size
(capacity) of the slab. Each element of the slab represents an
array, of length 'stride', of 'elemtype'. (Note that it may be
clearer if the define_commit_slab macro parameter was called
'basetype' rather than 'elemtype'). However, the 'elem_size'
calculation incorrectly uses 'sizeof(struct slabname)' in the
expression, rather than 'sizeof(elemtype)'.
Within the slab access routine, <slabname>_at(), the given commit
'index' is transformed into an (slab#, slot#) pair used to address
the required element (a pointer to the first element of the array
of 'elemtype' associated with that commit). The current code to
calculate these address coordinates multiplies the commit index
by the 'stride' which, at least for the slab#, produces the wrong
result. Using the commit index directly, without scaling by the
'stride', produces the correct 'logical' address.
Also, when allocating a new slab, the size of the allocation only
allows for a slab containing elements of single element arrays of
'elemtype'. This should allow for elements of an array of length
'stride' of 'elemtype'. In order to fix this, we need to change
the element size parameter to xcalloc() by multiplying the current
element size (sizeof(**s->slab)) by the s->stride.
Having changed the calculation of the slot#, we now need to convert
the logical 'nth_slot', by scaling with s->stride, into the correct
physical address.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-28 03:00:07 +08:00
|
|
|
elem_size = sizeof(elemtype) * stride; \
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
s->slab_size = COMMIT_SLAB_SIZE / elem_size; \
|
|
|
|
s->slab_count = 0; \
|
|
|
|
s->slab = NULL; \
|
|
|
|
} \
|
|
|
|
\
|
2013-11-26 04:04:08 +08:00
|
|
|
static MAYBE_UNUSED void init_ ##slabname(struct slabname *s) \
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
{ \
|
|
|
|
init_ ##slabname## _with_stride(s, 1); \
|
|
|
|
} \
|
|
|
|
\
|
2013-11-26 04:04:08 +08:00
|
|
|
static MAYBE_UNUSED void clear_ ##slabname(struct slabname *s) \
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
{ \
|
|
|
|
int i; \
|
|
|
|
for (i = 0; i < s->slab_count; i++) \
|
|
|
|
free(s->slab[i]); \
|
|
|
|
s->slab_count = 0; \
|
|
|
|
free(s->slab); \
|
|
|
|
s->slab = NULL; \
|
|
|
|
} \
|
|
|
|
\
|
2015-05-15 06:25:52 +08:00
|
|
|
static MAYBE_UNUSED elemtype *slabname## _at_peek(struct slabname *s, \
|
|
|
|
const struct commit *c, \
|
|
|
|
int add_if_missing) \
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
{ \
|
commit-slab.h: Fix memory allocation and addressing
The slab initialization code includes the calculation of the
slab 'elem_size', which is in turn used to determine the size
(capacity) of the slab. Each element of the slab represents an
array, of length 'stride', of 'elemtype'. (Note that it may be
clearer if the define_commit_slab macro parameter was called
'basetype' rather than 'elemtype'). However, the 'elem_size'
calculation incorrectly uses 'sizeof(struct slabname)' in the
expression, rather than 'sizeof(elemtype)'.
Within the slab access routine, <slabname>_at(), the given commit
'index' is transformed into an (slab#, slot#) pair used to address
the required element (a pointer to the first element of the array
of 'elemtype' associated with that commit). The current code to
calculate these address coordinates multiplies the commit index
by the 'stride' which, at least for the slab#, produces the wrong
result. Using the commit index directly, without scaling by the
'stride', produces the correct 'logical' address.
Also, when allocating a new slab, the size of the allocation only
allows for a slab containing elements of single element arrays of
'elemtype'. This should allow for elements of an array of length
'stride' of 'elemtype'. In order to fix this, we need to change
the element size parameter to xcalloc() by multiplying the current
element size (sizeof(**s->slab)) by the s->stride.
Having changed the calculation of the slot#, we now need to convert
the logical 'nth_slot', by scaling with s->stride, into the correct
physical address.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-28 03:00:07 +08:00
|
|
|
int nth_slab, nth_slot; \
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
\
|
commit-slab.h: Fix memory allocation and addressing
The slab initialization code includes the calculation of the
slab 'elem_size', which is in turn used to determine the size
(capacity) of the slab. Each element of the slab represents an
array, of length 'stride', of 'elemtype'. (Note that it may be
clearer if the define_commit_slab macro parameter was called
'basetype' rather than 'elemtype'). However, the 'elem_size'
calculation incorrectly uses 'sizeof(struct slabname)' in the
expression, rather than 'sizeof(elemtype)'.
Within the slab access routine, <slabname>_at(), the given commit
'index' is transformed into an (slab#, slot#) pair used to address
the required element (a pointer to the first element of the array
of 'elemtype' associated with that commit). The current code to
calculate these address coordinates multiplies the commit index
by the 'stride' which, at least for the slab#, produces the wrong
result. Using the commit index directly, without scaling by the
'stride', produces the correct 'logical' address.
Also, when allocating a new slab, the size of the allocation only
allows for a slab containing elements of single element arrays of
'elemtype'. This should allow for elements of an array of length
'stride' of 'elemtype'. In order to fix this, we need to change
the element size parameter to xcalloc() by multiplying the current
element size (sizeof(**s->slab)) by the s->stride.
Having changed the calculation of the slot#, we now need to convert
the logical 'nth_slot', by scaling with s->stride, into the correct
physical address.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-28 03:00:07 +08:00
|
|
|
nth_slab = c->index / s->slab_size; \
|
|
|
|
nth_slot = c->index % s->slab_size; \
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
\
|
|
|
|
if (s->slab_count <= nth_slab) { \
|
|
|
|
int i; \
|
2015-05-15 06:25:52 +08:00
|
|
|
if (!add_if_missing) \
|
|
|
|
return NULL; \
|
2014-09-17 02:56:57 +08:00
|
|
|
REALLOC_ARRAY(s->slab, nth_slab + 1); \
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
stat_ ##slabname## realloc++; \
|
|
|
|
for (i = s->slab_count; i <= nth_slab; i++) \
|
|
|
|
s->slab[i] = NULL; \
|
|
|
|
s->slab_count = nth_slab + 1; \
|
|
|
|
} \
|
2015-05-15 06:25:52 +08:00
|
|
|
if (!s->slab[nth_slab]) { \
|
|
|
|
if (!add_if_missing) \
|
|
|
|
return NULL; \
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
s->slab[nth_slab] = xcalloc(s->slab_size, \
|
commit-slab.h: Fix memory allocation and addressing
The slab initialization code includes the calculation of the
slab 'elem_size', which is in turn used to determine the size
(capacity) of the slab. Each element of the slab represents an
array, of length 'stride', of 'elemtype'. (Note that it may be
clearer if the define_commit_slab macro parameter was called
'basetype' rather than 'elemtype'). However, the 'elem_size'
calculation incorrectly uses 'sizeof(struct slabname)' in the
expression, rather than 'sizeof(elemtype)'.
Within the slab access routine, <slabname>_at(), the given commit
'index' is transformed into an (slab#, slot#) pair used to address
the required element (a pointer to the first element of the array
of 'elemtype' associated with that commit). The current code to
calculate these address coordinates multiplies the commit index
by the 'stride' which, at least for the slab#, produces the wrong
result. Using the commit index directly, without scaling by the
'stride', produces the correct 'logical' address.
Also, when allocating a new slab, the size of the allocation only
allows for a slab containing elements of single element arrays of
'elemtype'. This should allow for elements of an array of length
'stride' of 'elemtype'. In order to fix this, we need to change
the element size parameter to xcalloc() by multiplying the current
element size (sizeof(**s->slab)) by the s->stride.
Having changed the calculation of the slot#, we now need to convert
the logical 'nth_slot', by scaling with s->stride, into the correct
physical address.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-28 03:00:07 +08:00
|
|
|
sizeof(**s->slab) * s->stride); \
|
2015-05-15 06:25:52 +08:00
|
|
|
} \
|
|
|
|
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); \
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
} \
|
|
|
|
\
|
|
|
|
static int stat_ ##slabname## realloc
|
|
|
|
|
2013-11-26 04:04:08 +08:00
|
|
|
/*
|
|
|
|
* Note that this seemingly redundant second declaration is required
|
|
|
|
* to allow a terminating semicolon, which makes instantiations look
|
|
|
|
* like function declarations. I.e., the expansion of
|
|
|
|
*
|
|
|
|
* define_commit_slab(indegree, int);
|
|
|
|
*
|
|
|
|
* ends in 'static int stat_indegreerealloc;'. This would otherwise
|
|
|
|
* be a syntax error according (at least) to ISO C. It's hard to
|
|
|
|
* catch because GCC silently parses it by default.
|
|
|
|
*/
|
|
|
|
|
2014-06-11 05:42:51 +08:00
|
|
|
/*
|
|
|
|
* Statically initialize a commit slab named "var". Note that this
|
|
|
|
* evaluates "stride" multiple times! Example:
|
|
|
|
*
|
|
|
|
* struct indegree indegrees = COMMIT_SLAB_INIT(1, indegrees);
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#define COMMIT_SLAB_INIT(stride, var) { \
|
|
|
|
COMMIT_SLAB_SIZE / sizeof(**((var).slab)) / (stride), \
|
|
|
|
(stride), 0, NULL \
|
|
|
|
}
|
|
|
|
|
commit-slab: introduce a macro to define a slab for new type
Introduce a header file to define a macro that can define the struct
type, initializer, accessor and cleanup functions to manage a commit
slab. Update the "indegree" topological sort facility using it.
To associate 32 flag bits with each commit, you can write:
define_commit_slab(flag32, uint32);
to declare "struct flag32" type, define an instance of it with
struct flag32 flags;
and initialize it by calling
init_flag32(&flags);
After that, a call to flag32_at() function
uint32 *fp = flag32_at(&flags, commit);
will return a pointer pointing at a uint32 for that commit. Once
you are done with these flags, clean them up with
clear_flag32(&flags);
Callers that cannot hard-code how wide the data to be associated
with the commit be at compile time can use the "_with_stride"
variant to initialize the slab.
Suppose you want to give one bit per existing ref, and paint commits
down to find which refs are descendants of each commit. Saying
typedef uint32 bits320[5];
define_commit_slab(flagbits, bits320);
at compile time will still limit your code with hard-coded limit,
because you may find that you have more than 320 refs at runtime.
The code can declare a commit slab "struct flagbits" like this
instead:
define_commit_slab(flagbits, unsigned char);
struct flagbits flags;
and initialize it by:
nrefs = ... count number of refs ...
init_flagbits_with_stride(&flags, (nrefs + 7) / 8);
so that
unsigned char *fp = flagbits_at(&flags, commit);
will return a pointer pointing at an array of 40 "unsigned char"s
associated with the commit, once you figure out nrefs is 320 at
runtime.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-04-14 02:56:41 +08:00
|
|
|
#endif /* COMMIT_SLAB_H */
|