]>
Commit | Line | Data |
---|---|---|
2bc8fa02 | 1 | /* |
359fc2d2 | 2 | * Copyright (C) the libgit2 contributors. All rights reserved. |
2bc8fa02 RB |
3 | * |
4 | * This file is part of libgit2, distributed under the GNU GPL v2 with | |
5 | * a Linking Exception. For full terms see the included COPYING file. | |
6 | */ | |
7 | #ifndef INCLUDE_pool_h__ | |
8 | #define INCLUDE_pool_h__ | |
9 | ||
10 | #include "common.h" | |
11 | ||
12 | typedef struct git_pool_page git_pool_page; | |
13 | ||
14 | /** | |
15 | * Chunked allocator. | |
16 | * | |
17 | * A `git_pool` can be used when you want to cheaply allocate | |
18 | * multiple items of the same type and are willing to free them | |
19 | * all together with a single call. The two most common cases | |
20 | * are a set of fixed size items (such as lots of OIDs) or a | |
21 | * bunch of strings. | |
22 | * | |
23 | * Internally, a `git_pool` allocates pages of memory and then | |
24 | * deals out blocks from the trailing unused portion of each page. | |
25 | * The pages guarantee that the number of actual allocations done | |
26 | * will be much smaller than the number of items needed. | |
27 | * | |
28 | * For examples of how to set up a `git_pool` see `git_pool_init`. | |
29 | */ | |
30 | typedef struct { | |
31 | git_pool_page *open; /* pages with space left */ | |
32 | git_pool_page *full; /* pages with no space left */ | |
33 | void *free_list; /* optional: list of freed blocks */ | |
34 | uint32_t item_size; /* size of single alloc unit in bytes */ | |
35 | uint32_t page_size; /* size of page in bytes */ | |
19fa2bc1 | 36 | uint32_t items; |
2bc8fa02 RB |
37 | unsigned has_string_alloc : 1; /* was the strdup function used */ |
38 | unsigned has_multi_item_alloc : 1; /* was items ever > 1 in malloc */ | |
39 | unsigned has_large_page_alloc : 1; /* are any pages > page_size */ | |
40 | } git_pool; | |
41 | ||
19fa2bc1 RB |
42 | #define GIT_POOL_INIT_STRINGPOOL { 0, 0, 0, 1, 4000, 0, 0, 0, 0 } |
43 | ||
2bc8fa02 RB |
44 | /** |
45 | * Initialize a pool. | |
46 | * | |
47 | * To allocation strings, use like this: | |
48 | * | |
49 | * git_pool_init(&string_pool, 1, 0); | |
50 | * my_string = git_pool_strdup(&string_pool, your_string); | |
51 | * | |
52 | * To allocate items of fixed size, use like this: | |
53 | * | |
54 | * git_pool_init(&pool, sizeof(item), 0); | |
19fa2bc1 | 55 | * my_item = git_pool_malloc(&pool, 1); |
2bc8fa02 RB |
56 | * |
57 | * Of course, you can use this in other ways, but those are the | |
58 | * two most common patterns. | |
59 | */ | |
60 | extern int git_pool_init( | |
61 | git_pool *pool, uint32_t item_size, uint32_t items_per_page); | |
62 | ||
63 | /** | |
64 | * Free all items in pool | |
65 | */ | |
66 | extern void git_pool_clear(git_pool *pool); | |
67 | ||
19fa2bc1 RB |
68 | /** |
69 | * Swap two pools with one another | |
70 | */ | |
71 | extern void git_pool_swap(git_pool *a, git_pool *b); | |
72 | ||
2bc8fa02 RB |
73 | /** |
74 | * Allocate space for one or more items from a pool. | |
75 | */ | |
19fa2bc1 | 76 | extern void *git_pool_malloc(git_pool *pool, uint32_t items); |
2bc8fa02 | 77 | |
f335ecd6 RB |
78 | /** |
79 | * Allocate space and zero it out. | |
80 | */ | |
81 | GIT_INLINE(void *) git_pool_mallocz(git_pool *pool, uint32_t items) | |
82 | { | |
83 | void *ptr = git_pool_malloc(pool, items); | |
84 | if (ptr) | |
85 | memset(ptr, 0, (size_t)items * (size_t)pool->item_size); | |
86 | return ptr; | |
87 | } | |
88 | ||
2bc8fa02 RB |
89 | /** |
90 | * Allocate space and duplicate string data into it. | |
91 | * | |
92 | * This is allowed only for pools with item_size == sizeof(char) | |
93 | */ | |
94 | extern char *git_pool_strndup(git_pool *pool, const char *str, size_t n); | |
95 | ||
96 | /** | |
97 | * Allocate space and duplicate a string into it. | |
98 | * | |
99 | * This is allowed only for pools with item_size == sizeof(char) | |
100 | */ | |
101 | extern char *git_pool_strdup(git_pool *pool, const char *str); | |
102 | ||
71d27358 RB |
103 | /** |
104 | * Allocate space and duplicate a string into it, NULL is no error. | |
105 | * | |
106 | * This is allowed only for pools with item_size == sizeof(char) | |
107 | */ | |
108 | extern char *git_pool_strdup_safe(git_pool *pool, const char *str); | |
109 | ||
19fa2bc1 RB |
110 | /** |
111 | * Allocate space for the concatenation of two strings. | |
112 | * | |
113 | * This is allowed only for pools with item_size == sizeof(char) | |
114 | */ | |
115 | extern char *git_pool_strcat(git_pool *pool, const char *a, const char *b); | |
116 | ||
2bc8fa02 RB |
117 | /** |
118 | * Push a block back onto the free list for the pool. | |
119 | * | |
120 | * This is allowed only if the item_size is >= sizeof(void*). | |
121 | * | |
122 | * In some cases, it is helpful to "release" an allocated block | |
123 | * for reuse. Pools don't support a general purpose free, but | |
124 | * they will keep a simple free blocks linked list provided the | |
125 | * native block size is large enough to hold a void pointer | |
126 | */ | |
127 | extern void git_pool_free(git_pool *pool, void *ptr); | |
128 | ||
0c468633 RB |
129 | /** |
130 | * Push an array of pool allocated blocks efficiently onto the free list. | |
131 | * | |
132 | * This has the same constraints as `git_pool_free()` above. | |
133 | */ | |
134 | extern void git_pool_free_array(git_pool *pool, size_t count, void **ptrs); | |
135 | ||
2bc8fa02 RB |
136 | /* |
137 | * Misc utilities | |
138 | */ | |
139 | ||
140 | extern uint32_t git_pool__open_pages(git_pool *pool); | |
141 | ||
142 | extern uint32_t git_pool__full_pages(git_pool *pool); | |
143 | ||
144 | extern bool git_pool__ptr_in_pool(git_pool *pool, void *ptr); | |
145 | ||
da3b391c RB |
146 | extern uint32_t git_pool__suggest_items_per_page(uint32_t item_size); |
147 | ||
2bc8fa02 | 148 | #endif |