chiark / gitweb /
Add adns support in background resolver.
[mLib] / pool.c
CommitLineData
d94be366 1/* -*-c-*-
2 *
c5775f49 3 * $Id: pool.c,v 1.2 2003/10/12 14:44:46 mdw Exp $
d94be366 4 *
5 * Resource pool handling
6 *
7 * (c) 2000 Straylight/Edgeware
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of the mLib utilities library.
13 *
14 * mLib is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * mLib is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public
25 * License along with mLib; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
30/*----- Revision history --------------------------------------------------*
31 *
32 * $Log: pool.c,v $
c5775f49 33 * Revision 1.2 2003/10/12 14:44:46 mdw
34 * Various fixes.
35 *
d94be366 36 * Revision 1.1 2000/07/16 12:28:48 mdw
37 * Support for resource pools, based on the Apache model.
38 *
39 */
40
41/*----- Header files ------------------------------------------------------*/
42
c5775f49 43#include "align.h"
d94be366 44#include "alloc.h"
45#include "arena.h"
46#include "pool.h"
47
48/*----- Main code ---------------------------------------------------------*/
49
50/* --- @doalloc@ --- *
51 *
52 * Arguments: @arena *a@ = pointer to arena to allocate memory from
53 * @pool_chunk **cc@ = pointer to chunk list
54 * @size_t sz@ = size of memory wanted
55 *
56 * Returns: Pointer to the allocated block.
57 *
58 * Use: The basic allocator for resource pools. This is also used
59 * during pool creation, hence the slightly bizarre interface.
60 */
61
62static void *doalloc(arena *a, pool_chunk **cc, size_t sz)
63{
64 pool_chunk *c;
65 void *p;
66 size_t csz, ssz;
67
d94be366 68 /* --- See if there's enough space --- *
69 *
70 * The chunks are sorted by available space, so if there's not enough space
71 * in the first chunk there isn't enough space anywhere.
72 */
73
c5775f49 74 ALIGN(sz);
d94be366 75 c = *cc;
76 if (c && c->left >= sz) {
77 p = c->p;
78 c->p += sz;
79 c->left -= sz;
80 *cc = c->next;
81 }
82
83 /* --- Failed to find anything --- *
84 *
85 * I must allocate a new block from the arena, then.
86 */
87
88 else {
c5775f49 89 ssz = sizeof(pool_chunk);
90 ALIGN(ssz);
91 csz = (ssz + sz + POOL_CHUNKSZ - 1); csz -= csz % POOL_CHUNKSZ;
92 c = x_alloc(a, csz);
d94be366 93 p = (char *)c + ssz;
94 c->p = (char *)p + sz;
95 c->left = csz - ssz - sz;
96 }
97
98 /* --- Move this chunk in the list so that it's sorted --- */
99
100 while (*cc && (*cc)->left > c->left)
101 cc = &(*cc)->next;
102 c->next = *cc;
103 *cc = c;
104
105 /* --- Done --- */
106
107 return (p);
d94be366 108}
109
110/* --- @pool_alloc@ --- *
111 *
112 * Arguments: @pool *p@ = pool to allocate from
113 * @size_t sz@ = size of block wanted
114 *
115 * Returns: Pointer to the requested block.
116 *
117 * Use: Allocates memory from a resource pool. Memory is never freed
118 * from pools: it is released when the pool is destroyed.
119 */
120
121void *pool_alloc(pool *p, size_t sz)
122{
123 return (doalloc(p->pa, &p->c, sz));
124}
125
126/* --- @pool_strdup@ --- *
127 *
128 * Arguments: @pool *p@ = pool to allocate from
129 * @const char *s@ = pointer to string
130 *
131 * Returns: A pointer to a copy of the string.
132 *
133 * Use: Allocates a copy of a string.
134 */
135
136char *pool_strdup(pool *p, const char *s)
137{
138 size_t sz = strlen(s) + 1;
139 char *pp = doalloc(p->pa, &p->c, sz);
140 memcpy(pp, s, sz);
141 return (pp);
142}
143
144/* --- Arena operations --- */
145
146static void *palloc(arena *a, size_t sz)
147{
148 pool *p = (pool *)a;
149 return (doalloc(p->pa, &p->c, sz));
150}
151
152static void pfree(arena *a, void *p) { return; } /* Trivial */
153
154static arena_ops pool_ops = { palloc, arena_fakerealloc, pfree, 0 };
155
c5775f49 156/* --- @pool_init@ --- *
157 *
158 * Arguments: @pool *p@ = pointer to the pool structure to initialize
159 * @arena *a@ = pointer to an arena to allocate memory from
160 *
161 * Returns: ---
162 *
163 * Use: Initializes a chunk of memory as a resource pool which is not
164 * a child of any other resource pool.
165 */
166
167void pool_init(pool *p, arena *a)
168{
169 p->a.ops = &pool_ops;
170 p->c = 0;
171 p->r = 0;
172 p->pa = a;
173}
174
d94be366 175/* --- @pool_create@ --- *
176 *
177 * Arguments: @arena *a@ = pointer to an arena to allocate memory from
178 *
179 * Returns: A newly created resource pool.
180 *
181 * Use: Creates a resource pool which is not a child of any other
182 * resource pool.
183 */
184
185pool *pool_create(arena *a)
186{
187 pool_chunk *c = 0;
188 pool *p = doalloc(a, &c, sizeof(pool));
c5775f49 189 pool_init(p, a);
d94be366 190 p->c = c;
d94be366 191 return (p);
192}
193
194/* --- @pool_destroy@ --- *
195 *
196 * Arguments: @pool *p@ = pointer to pool to destroy
197 *
198 * Returns: ---
199 *
200 * Use: Destroys a pool, freeing all of the resources within it. If
c5775f49 201 * this is a pool created by @pool_create@, its memory will be
202 * deallocated; if it's a subpool or it was initialized by
203 * @pool_init@, it is emptied and can be used again.
d94be366 204 */
205
206void pool_destroy(pool *p)
207{
208 pool_resource *r, *rr;
209 arena *a;
210 pool_chunk *c, *cc;
211
212 /* --- Dispose of all of the resources --- */
213
214 r = p->r;
215 while (r) {
216 rr = r->next;
217 if (r->destroy)
218 r->destroy(r);
219 r = rr;
220 }
221 p->r = 0;
222
223 /* --- Free all of the memory --- *
224 *
225 * Since root pools are allocated in their own memory, this will free the
226 * root pool block. Subpools are allocated in their parent's memory, so
227 * the pool block itself will be left around.
228 */
229
230 a = p->pa;
231 c = p->c;
232 p->c = 0;
233 while (c) {
234 cc = c->next;
235 x_free(a, c);
236 c = cc;
237 }
238}
239
240/* --- @pool_add@ --- *
241 *
242 * Arguments: @pool *p@ = pointer to pool to add the resource to
243 * @pool_resource *r@ = pointer to resource block
244 * @void (*dfn)(pool_resource *r)@ = destruction function
245 *
246 * Returns: ---
247 *
248 * Use: Adds a resource to a pool.
249 */
250
251void pool_add(pool *p, pool_resource *r, void (*dfn)(pool_resource *r))
252{
253 POOL_ADD(p, r, dfn);
254}
255
256/* --- @pool_sub@ --- *
257 *
258 * Arguments: @pool *p@ = pointer to parent pool
259 *
260 * Returns: A new child pool of the parent.
261 *
262 * Use: Creates a subpool. The subpool can either be destroyed on
263 * its own, or will be automatically destroyed at the same time
264 * as the parent.
265 */
266
267typedef struct subpool {
268 pool_resource r;
269 pool p;
270} subpool;
271
272static void subpool_destroy(pool_resource *r)
273{
274 subpool *p = (subpool *)r;
275 pool_destroy(&p->p);
276}
277
278pool *pool_sub(pool *p)
279{
280 subpool *pp = pool_alloc(p, sizeof(subpool));
281 POOL_ADD(p, &pp->r, subpool_destroy);
282 pp->p.a.ops = &pool_ops;
283 pp->p.c = 0;
284 pp->p.r = 0;
285 pp->p.pa = p->pa;
286 return (&pp->p);
287}
288
289/*----- That's all, folks -------------------------------------------------*/