1#ifndef COMMIT_SLAB_IMPL_H
2#define COMMIT_SLAB_IMPL_H
3
4#define MAYBE_UNUSED __attribute__((__unused__))
5
6#define implement_static_commit_slab(slabname, elemtype) \
7 implement_commit_slab(slabname, elemtype, static MAYBE_UNUSED)
8
9#define implement_shared_commit_slab(slabname, elemtype) \
10 implement_commit_slab(slabname, elemtype, )
11
12#define implement_commit_slab(slabname, elemtype, scope) \
13 \
14static int stat_ ##slabname## realloc; \
15 \
16scope 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} \
28 \
29scope void init_ ##slabname(struct slabname *s) \
30{ \
31 init_ ##slabname## _with_stride(s, 1); \
32} \
33 \
34scope 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} \
42 \
43scope 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; \
48 \
49 nth_slab = c->index / s->slab_size; \
50 nth_slot = c->index % s->slab_size; \
51 \
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} \
70 \
71scope elemtype *slabname## _at(struct slabname *s, \
72 const struct commit *c) \
73{ \
74 return slabname##_at_peek(s, c, 1); \
75} \
76 \
77scope elemtype *slabname## _peek(struct slabname *s, \
78 const struct commit *c) \
79{ \
80 return slabname##_at_peek(s, c, 0); \
81} \
82 \
83struct slabname
84
85/*
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
89 *
90 * implement_commit_slab(indegree, int, static);
91 *
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.
95 */
96
97#endif /* COMMIT_SLAB_IMPL_H */