get_shallow_commits: Avoid memory leak if a commit has been reached already.
[git] / alloc.c
1 /*
2  * alloc.c  - specialized allocator for internal objects
3  *
4  * Copyright (C) 2006 Linus Torvalds
5  *
6  * The standard malloc/free wastes too much space for objects, partly because
7  * it maintains all the allocation infrastructure (which isn't needed, since
8  * we never free an object descriptor anyway), but even more because it ends
9  * up with maximal alignment because it doesn't know what the object alignment
10  * for the new allocation is.
11  */
12 #include "cache.h"
13 #include "object.h"
14 #include "blob.h"
15 #include "tree.h"
16 #include "commit.h"
17 #include "tag.h"
18
19 #define BLOCKING 1024
20
21 #define DEFINE_ALLOCATOR(name)                                  \
22 static unsigned int name##_allocs;                              \
23 struct name *alloc_##name##_node(void)                          \
24 {                                                               \
25         static int nr;                                          \
26         static struct name *block;                              \
27                                                                 \
28         if (!nr) {                                              \
29                 nr = BLOCKING;                                  \
30                 block = xcalloc(BLOCKING, sizeof(struct name)); \
31         }                                                       \
32         nr--;                                                   \
33         name##_allocs++;                                        \
34         return block++;                                         \
35 }
36
37 DEFINE_ALLOCATOR(blob)
38 DEFINE_ALLOCATOR(tree)
39 DEFINE_ALLOCATOR(commit)
40 DEFINE_ALLOCATOR(tag)
41
42 #ifdef NO_C99_FORMAT
43 #define SZ_FMT "%u"
44 #else
45 #define SZ_FMT "%zu"
46 #endif
47
48 static void report(const char* name, unsigned int count, size_t size)
49 {
50     fprintf(stderr, "%10s: %8u (" SZ_FMT " kB)\n", name, count, size);
51 }
52
53 #undef SZ_FMT
54
55 #define REPORT(name)    \
56     report(#name, name##_allocs, name##_allocs*sizeof(struct name) >> 10)
57
58 void alloc_report(void)
59 {
60         REPORT(blob);
61         REPORT(tree);
62         REPORT(commit);
63         REPORT(tag);
64 }