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 |
| 25 | * that id initialied by the variant without "_with_stride" associates |
| 26 | * each commit with an array of one integer. |
| 27 | */ |
| 28 | |
| 29 | /* allocate ~512kB at once, allowing for malloc overhead */ |
| 30 | #ifndef COMMIT_SLAB_SIZE |
| 31 | #define COMMIT_SLAB_SIZE (512*1024-32) |
| 32 | #endif |
| 33 | |
| 34 | #define define_commit_slab(slabname, elemtype) \ |
| 35 | \ |
| 36 | struct slabname { \ |
| 37 | unsigned slab_size; \ |
| 38 | unsigned stride; \ |
| 39 | unsigned slab_count; \ |
| 40 | elemtype **slab; \ |
| 41 | }; \ |
| 42 | static int stat_ ##slabname## realloc; \ |
| 43 | \ |
| 44 | static void init_ ##slabname## _with_stride(struct slabname *s, \ |
| 45 | unsigned stride) \ |
| 46 | { \ |
| 47 | unsigned int elem_size; \ |
| 48 | if (!stride) \ |
| 49 | stride = 1; \ |
| 50 | s->stride = stride; \ |
Ramsay Jones | d7a1d62 | 2013-07-27 20:00:07 +0100 | [diff] [blame] | 51 | elem_size = sizeof(elemtype) * stride; \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 52 | s->slab_size = COMMIT_SLAB_SIZE / elem_size; \ |
| 53 | s->slab_count = 0; \ |
| 54 | s->slab = NULL; \ |
| 55 | } \ |
| 56 | \ |
| 57 | static void init_ ##slabname(struct slabname *s) \ |
| 58 | { \ |
| 59 | init_ ##slabname## _with_stride(s, 1); \ |
| 60 | } \ |
| 61 | \ |
| 62 | static void clear_ ##slabname(struct slabname *s) \ |
| 63 | { \ |
| 64 | int i; \ |
| 65 | for (i = 0; i < s->slab_count; i++) \ |
| 66 | free(s->slab[i]); \ |
| 67 | s->slab_count = 0; \ |
| 68 | free(s->slab); \ |
| 69 | s->slab = NULL; \ |
| 70 | } \ |
| 71 | \ |
| 72 | static elemtype *slabname## _at(struct slabname *s, \ |
| 73 | const struct commit *c) \ |
| 74 | { \ |
Ramsay Jones | d7a1d62 | 2013-07-27 20:00:07 +0100 | [diff] [blame] | 75 | int nth_slab, nth_slot; \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 76 | \ |
Ramsay Jones | d7a1d62 | 2013-07-27 20:00:07 +0100 | [diff] [blame] | 77 | nth_slab = c->index / s->slab_size; \ |
| 78 | nth_slot = c->index % s->slab_size; \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 79 | \ |
| 80 | if (s->slab_count <= nth_slab) { \ |
| 81 | int i; \ |
| 82 | s->slab = xrealloc(s->slab, \ |
| 83 | (nth_slab + 1) * sizeof(s->slab)); \ |
| 84 | stat_ ##slabname## realloc++; \ |
| 85 | for (i = s->slab_count; i <= nth_slab; i++) \ |
| 86 | s->slab[i] = NULL; \ |
| 87 | s->slab_count = nth_slab + 1; \ |
| 88 | } \ |
| 89 | if (!s->slab[nth_slab]) \ |
| 90 | s->slab[nth_slab] = xcalloc(s->slab_size, \ |
Ramsay Jones | d7a1d62 | 2013-07-27 20:00:07 +0100 | [diff] [blame] | 91 | sizeof(**s->slab) * s->stride); \ |
| 92 | return &s->slab[nth_slab][nth_slot * s->stride]; \ |
Junio C Hamano | a84b794 | 2013-04-13 11:56:41 -0700 | [diff] [blame] | 93 | } \ |
| 94 | \ |
| 95 | static int stat_ ##slabname## realloc |
| 96 | |
| 97 | #endif /* COMMIT_SLAB_H */ |