Merge branch 'jk/log-follow-with-non-literal-pathspec'
[alt-git.git] / commit-slab-impl.h
blob4a414ee905d5de4498d1fcca2da53e7c6a07b50e
1 #ifndef COMMIT_SLAB_IMPL_H
2 #define COMMIT_SLAB_IMPL_H
4 #define implement_static_commit_slab(slabname, elemtype) \
5 implement_commit_slab(slabname, elemtype, MAYBE_UNUSED static)
7 #define implement_shared_commit_slab(slabname, elemtype) \
8 implement_commit_slab(slabname, elemtype, )
10 #define implement_commit_slab(slabname, elemtype, scope) \
12 scope void init_ ##slabname## _with_stride(struct slabname *s, \
13 unsigned stride) \
14 { \
15 unsigned int elem_size; \
16 if (!stride) \
17 stride = 1; \
18 s->stride = stride; \
19 elem_size = sizeof(elemtype) * stride; \
20 s->slab_size = COMMIT_SLAB_SIZE / elem_size; \
21 s->slab_count = 0; \
22 s->slab = NULL; \
23 } \
25 scope void init_ ##slabname(struct slabname *s) \
26 { \
27 init_ ##slabname## _with_stride(s, 1); \
28 } \
30 scope void clear_ ##slabname(struct slabname *s) \
31 { \
32 unsigned int i; \
33 for (i = 0; i < s->slab_count; i++) \
34 free(s->slab[i]); \
35 s->slab_count = 0; \
36 FREE_AND_NULL(s->slab); \
37 } \
39 scope void deep_clear_ ##slabname(struct slabname *s, void (*free_fn)(elemtype *)) \
40 { \
41 unsigned int i; \
42 for (i = 0; i < s->slab_count; i++) { \
43 unsigned int j; \
44 if (!s->slab[i]) \
45 continue; \
46 for (j = 0; j < s->slab_size; j++) \
47 free_fn(&s->slab[i][j * s->stride]); \
48 } \
49 clear_ ##slabname(s); \
50 } \
52 scope elemtype *slabname## _at_peek(struct slabname *s, \
53 const struct commit *c, \
54 int add_if_missing) \
55 { \
56 unsigned int nth_slab, nth_slot; \
58 nth_slab = c->index / s->slab_size; \
59 nth_slot = c->index % s->slab_size; \
61 if (s->slab_count <= nth_slab) { \
62 unsigned int i; \
63 if (!add_if_missing) \
64 return NULL; \
65 REALLOC_ARRAY(s->slab, nth_slab + 1); \
66 for (i = s->slab_count; i <= nth_slab; i++) \
67 s->slab[i] = NULL; \
68 s->slab_count = nth_slab + 1; \
69 } \
70 if (!s->slab[nth_slab]) { \
71 if (!add_if_missing) \
72 return NULL; \
73 s->slab[nth_slab] = xcalloc(s->slab_size, \
74 sizeof(**s->slab) * s->stride); \
75 } \
76 return &s->slab[nth_slab][nth_slot * s->stride]; \
77 } \
79 scope elemtype *slabname## _at(struct slabname *s, \
80 const struct commit *c) \
81 { \
82 return slabname##_at_peek(s, c, 1); \
83 } \
85 scope elemtype *slabname## _peek(struct slabname *s, \
86 const struct commit *c) \
87 { \
88 return slabname##_at_peek(s, c, 0); \
89 } \
91 struct slabname
94 * Note that this redundant forward declaration is required
95 * to allow a terminating semicolon, which makes instantiations look
96 * like function declarations. I.e., the expansion of
98 * implement_commit_slab(indegree, int, static);
100 * ends in 'struct indegree;'. This would otherwise
101 * be a syntax error according (at least) to ISO C. It's hard to
102 * catch because GCC silently parses it by default.
105 #endif /* COMMIT_SLAB_IMPL_H */