Merge branch 'sg/gpg-tests-fix'
[git.git] / commit-slab-impl.h
blob87a9cadfcca3f58045e2d7b2c3a143c8c4501f8d
1 #ifndef COMMIT_SLAB_IMPL_H
2 #define COMMIT_SLAB_IMPL_H
4 #define MAYBE_UNUSED __attribute__((__unused__))
6 #define implement_static_commit_slab(slabname, elemtype) \
7 implement_commit_slab(slabname, elemtype, static MAYBE_UNUSED)
9 #define implement_shared_commit_slab(slabname, elemtype) \
10 implement_commit_slab(slabname, elemtype, )
12 #define implement_commit_slab(slabname, elemtype, scope) \
14 static int stat_ ##slabname## realloc; \
16 scope void init_ ##slabname## _with_stride(struct slabname *s, \
17 unsigned stride) \
18 { \
19 unsigned int elem_size; \
20 if (!stride) \
21 stride = 1; \
22 s->stride = stride; \
23 elem_size = sizeof(elemtype) * stride; \
24 s->slab_size = COMMIT_SLAB_SIZE / elem_size; \
25 s->slab_count = 0; \
26 s->slab = NULL; \
27 } \
29 scope void init_ ##slabname(struct slabname *s) \
30 { \
31 init_ ##slabname## _with_stride(s, 1); \
32 } \
34 scope void clear_ ##slabname(struct slabname *s) \
35 { \
36 unsigned int i; \
37 for (i = 0; i < s->slab_count; i++) \
38 free(s->slab[i]); \
39 s->slab_count = 0; \
40 FREE_AND_NULL(s->slab); \
41 } \
43 scope elemtype *slabname## _at_peek(struct slabname *s, \
44 const struct commit *c, \
45 int add_if_missing) \
46 { \
47 unsigned int nth_slab, nth_slot; \
49 nth_slab = c->index / s->slab_size; \
50 nth_slot = c->index % s->slab_size; \
52 if (s->slab_count <= nth_slab) { \
53 unsigned int i; \
54 if (!add_if_missing) \
55 return NULL; \
56 REALLOC_ARRAY(s->slab, nth_slab + 1); \
57 stat_ ##slabname## realloc++; \
58 for (i = s->slab_count; i <= nth_slab; i++) \
59 s->slab[i] = NULL; \
60 s->slab_count = nth_slab + 1; \
61 } \
62 if (!s->slab[nth_slab]) { \
63 if (!add_if_missing) \
64 return NULL; \
65 s->slab[nth_slab] = xcalloc(s->slab_size, \
66 sizeof(**s->slab) * s->stride); \
67 } \
68 return &s->slab[nth_slab][nth_slot * s->stride]; \
69 } \
71 scope elemtype *slabname## _at(struct slabname *s, \
72 const struct commit *c) \
73 { \
74 return slabname##_at_peek(s, c, 1); \
75 } \
77 scope elemtype *slabname## _peek(struct slabname *s, \
78 const struct commit *c) \
79 { \
80 return slabname##_at_peek(s, c, 0); \
81 } \
83 struct slabname
86 * Note that this redundant forward declaration is required
87 * to allow a terminating semicolon, which makes instantiations look
88 * like function declarations. I.e., the expansion of
90 * implement_commit_slab(indegree, int, static);
92 * ends in 'struct indegree;'. This would otherwise
93 * be a syntax error according (at least) to ISO C. It's hard to
94 * catch because GCC silently parses it by default.
97 #endif /* COMMIT_SLAB_IMPL_H */