Git fork
at reftables-rust 105 lines 3.1 kB view raw
1#ifndef COMMIT_SLAB_IMPL_H 2#define COMMIT_SLAB_IMPL_H 3 4#define implement_static_commit_slab(slabname, elemtype) \ 5 implement_commit_slab(slabname, elemtype, MAYBE_UNUSED static) 6 7#define implement_shared_commit_slab(slabname, elemtype) \ 8 implement_commit_slab(slabname, elemtype, ) 9 10#define implement_commit_slab(slabname, elemtype, scope) \ 11 \ 12scope 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} \ 24 \ 25scope void init_ ##slabname(struct slabname *s) \ 26{ \ 27 init_ ##slabname## _with_stride(s, 1); \ 28} \ 29 \ 30scope 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} \ 38 \ 39scope 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} \ 51 \ 52scope 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; \ 57 \ 58 nth_slab = c->index / s->slab_size; \ 59 nth_slot = c->index % s->slab_size; \ 60 \ 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} \ 78 \ 79scope elemtype *slabname## _at(struct slabname *s, \ 80 const struct commit *c) \ 81{ \ 82 return slabname##_at_peek(s, c, 1); \ 83} \ 84 \ 85scope elemtype *slabname## _peek(struct slabname *s, \ 86 const struct commit *c) \ 87{ \ 88 return slabname##_at_peek(s, c, 0); \ 89} \ 90 \ 91struct slabname 92 93/* 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 97 * 98 * implement_commit_slab(indegree, int, static); 99 * 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. 103 */ 104 105#endif /* COMMIT_SLAB_IMPL_H */