Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 1 | #ifndef COMMIT_SLAB_H |
| 2 | #define COMMIT_SLAB_H |
| 3 | |
| 4 | /* |
| 5 | * define_commit_slab(slabname, elemtype) creates boilerplate code to define |
| 6 | * a new struct (struct slabname) that is used to associate a piece of data |
| 7 | * of elemtype to commits, and a few functions to use that struct. |
| 8 | * |
| 9 | * After including this header file, using: |
| 10 | * |
| 11 | * define_commit_slab(indegee, int); |
| 12 | * |
| 13 | * will let you call the following functions: |
| 14 | * |
| 15 | * - int *indegree_at(struct indegree *, struct commit *); |
| 16 | * |
| 17 | * This function locates the data associated with the given commit in |
| 18 | * the indegree slab, and returns the pointer to it. |
| 19 | * |
| 20 | * - void init_indegree(struct indegree *); |
| 21 | * void init_indegree_with_stride(struct indegree *, int); |
| 22 | * |
| 23 | * Initializes the indegree slab that associates an array of integers |
| 24 | * to each commit. 'stride' specifies how big each array is. The slab |
Thomas Rast | dcbbc8f | 2013-11-25 20:02:00 +0100 | [diff] [blame] | 25 | * that is initialized by the variant without "_with_stride" associates |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 26 | * each commit with an array of one integer. |
Thomas Rast | dcbbc8f | 2013-11-25 20:02:00 +0100 | [diff] [blame] | 27 | * |
| 28 | * - void clear_indegree(struct indegree *); |
| 29 | * |
| 30 | * Empties the slab. The slab can be reused with the same stride |
| 31 | * without calling init_indegree() again or can be reconfigured to a |
| 32 | * different stride by calling init_indegree_with_stride(). |
| 33 | * |
| 34 | * Call this function before the slab falls out of scope to avoid |
| 35 | * leaking memory. |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 36 | */ |
| 37 | |
| 38 | /* allocate ~512kB at once, allowing for malloc overhead */ |
| 39 | #ifndef COMMIT_SLAB_SIZE |
| 40 | #define COMMIT_SLAB_SIZE (512*1024-32) |
| 41 | #endif |
| 42 | |
Thomas Rast | e9e03a7 | 2013-11-25 21:04:08 +0100 | [diff] [blame] | 43 | #define MAYBE_UNUSED __attribute__((__unused__)) |
| 44 | |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 45 | #define define_commit_slab(slabname, elemtype) \ |
| 46 | \ |
| 47 | struct slabname { \ |
| 48 | unsigned slab_size; \ |
| 49 | unsigned stride; \ |
| 50 | unsigned slab_count; \ |
| 51 | elemtype **slab; \ |
| 52 | }; \ |
| 53 | static int stat_ ##slabname## realloc; \ |
| 54 | \ |
Thomas Rast | e9e03a7 | 2013-11-25 21:04:08 +0100 | [diff] [blame] | 55 | static MAYBE_UNUSED void init_ ##slabname## _with_stride(struct slabname *s, \ |
| 56 | unsigned stride) \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 57 | { \ |
| 58 | unsigned int elem_size; \ |
| 59 | if (!stride) \ |
| 60 | stride = 1; \ |
| 61 | s->stride = stride; \ |
Ramsay Jones | d7a1d62 | 2013-07-27 20:00:07 +0100 | [diff] [blame] | 62 | elem_size = sizeof(elemtype) * stride; \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 63 | s->slab_size = COMMIT_SLAB_SIZE / elem_size; \ |
| 64 | s->slab_count = 0; \ |
| 65 | s->slab = NULL; \ |
| 66 | } \ |
| 67 | \ |
Thomas Rast | e9e03a7 | 2013-11-25 21:04:08 +0100 | [diff] [blame] | 68 | static MAYBE_UNUSED void init_ ##slabname(struct slabname *s) \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 69 | { \ |
| 70 | init_ ##slabname## _with_stride(s, 1); \ |
| 71 | } \ |
| 72 | \ |
Thomas Rast | e9e03a7 | 2013-11-25 21:04:08 +0100 | [diff] [blame] | 73 | static MAYBE_UNUSED void clear_ ##slabname(struct slabname *s) \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 74 | { \ |
| 75 | int i; \ |
| 76 | for (i = 0; i < s->slab_count; i++) \ |
| 77 | free(s->slab[i]); \ |
| 78 | s->slab_count = 0; \ |
| 79 | free(s->slab); \ |
| 80 | s->slab = NULL; \ |
| 81 | } \ |
| 82 | \ |
Thomas Rast | e9e03a7 | 2013-11-25 21:04:08 +0100 | [diff] [blame] | 83 | static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \ |
| 84 | const struct commit *c) \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 85 | { \ |
Ramsay Jones | d7a1d62 | 2013-07-27 20:00:07 +0100 | [diff] [blame] | 86 | int nth_slab, nth_slot; \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 87 | \ |
Ramsay Jones | d7a1d62 | 2013-07-27 20:00:07 +0100 | [diff] [blame] | 88 | nth_slab = c->index / s->slab_size; \ |
| 89 | nth_slot = c->index % s->slab_size; \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 90 | \ |
| 91 | if (s->slab_count <= nth_slab) { \ |
| 92 | int i; \ |
| 93 | s->slab = xrealloc(s->slab, \ |
Thomas Rast | cde0a05 | 2013-12-01 21:41:55 +0100 | [diff] [blame] | 94 | (nth_slab + 1) * sizeof(*s->slab)); \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 95 | stat_ ##slabname## realloc++; \ |
| 96 | for (i = s->slab_count; i <= nth_slab; i++) \ |
| 97 | s->slab[i] = NULL; \ |
| 98 | s->slab_count = nth_slab + 1; \ |
| 99 | } \ |
| 100 | if (!s->slab[nth_slab]) \ |
| 101 | s->slab[nth_slab] = xcalloc(s->slab_size, \ |
Ramsay Jones | d7a1d62 | 2013-07-27 20:00:07 +0100 | [diff] [blame] | 102 | sizeof(**s->slab) * s->stride); \ |
| 103 | return &s->slab[nth_slab][nth_slot * s->stride]; \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 104 | } \ |
| 105 | \ |
| 106 | static int stat_ ##slabname## realloc |
| 107 | |
Thomas Rast | e9e03a7 | 2013-11-25 21:04:08 +0100 | [diff] [blame] | 108 | /* |
| 109 | * Note that this seemingly redundant second declaration is required |
| 110 | * to allow a terminating semicolon, which makes instantiations look |
| 111 | * like function declarations. I.e., the expansion of |
| 112 | * |
| 113 | * define_commit_slab(indegree, int); |
| 114 | * |
| 115 | * ends in 'static int stat_indegreerealloc;'. This would otherwise |
| 116 | * be a syntax error according (at least) to ISO C. It's hard to |
| 117 | * catch because GCC silently parses it by default. |
| 118 | */ |
| 119 | |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 120 | #endif /* COMMIT_SLAB_H */ |