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