3 * $Id: pool.c,v 1.2 2003/10/12 14:44:46 mdw Exp $
5 * Resource pool handling
7 * (c) 2000 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of the mLib utilities library.
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.
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.
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,
30 /*----- Revision history --------------------------------------------------*
33 * Revision 1.2 2003/10/12 14:44:46 mdw
36 * Revision 1.1 2000/07/16 12:28:48 mdw
37 * Support for resource pools, based on the Apache model.
41 /*----- Header files ------------------------------------------------------*/
48 /*----- Main code ---------------------------------------------------------*/
50 /* --- @doalloc@ --- *
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
56 * Returns: Pointer to the allocated block.
58 * Use: The basic allocator for resource pools. This is also used
59 * during pool creation, hence the slightly bizarre interface.
62 static void *doalloc(arena
*a
, pool_chunk
**cc
, size_t sz
)
68 /* --- See if there's enough space --- *
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.
76 if (c
&& c
->left
>= sz
) {
83 /* --- Failed to find anything --- *
85 * I must allocate a new block from the arena, then.
89 ssz
= sizeof(pool_chunk
);
91 csz
= (ssz
+ sz
+ POOL_CHUNKSZ
- 1); csz
-= csz
% POOL_CHUNKSZ
;
94 c
->p
= (char *)p
+ sz
;
95 c
->left
= csz
- ssz
- sz
;
98 /* --- Move this chunk in the list so that it's sorted --- */
100 while (*cc
&& (*cc
)->left
> c
->left
)
110 /* --- @pool_alloc@ --- *
112 * Arguments: @pool *p@ = pool to allocate from
113 * @size_t sz@ = size of block wanted
115 * Returns: Pointer to the requested block.
117 * Use: Allocates memory from a resource pool. Memory is never freed
118 * from pools: it is released when the pool is destroyed.
121 void *pool_alloc(pool
*p
, size_t sz
)
123 return (doalloc(p
->pa
, &p
->c
, sz
));
126 /* --- @pool_strdup@ --- *
128 * Arguments: @pool *p@ = pool to allocate from
129 * @const char *s@ = pointer to string
131 * Returns: A pointer to a copy of the string.
133 * Use: Allocates a copy of a string.
136 char *pool_strdup(pool
*p
, const char *s
)
138 size_t sz
= strlen(s
) + 1;
139 char *pp
= doalloc(p
->pa
, &p
->c
, sz
);
144 /* --- Arena operations --- */
146 static void *palloc(arena
*a
, size_t sz
)
149 return (doalloc(p
->pa
, &p
->c
, sz
));
152 static void pfree(arena
*a
, void *p
) { return; } /* Trivial */
154 static arena_ops pool_ops
= { palloc
, arena_fakerealloc
, pfree
, 0 };
156 /* --- @pool_init@ --- *
158 * Arguments: @pool *p@ = pointer to the pool structure to initialize
159 * @arena *a@ = pointer to an arena to allocate memory from
163 * Use: Initializes a chunk of memory as a resource pool which is not
164 * a child of any other resource pool.
167 void pool_init(pool
*p
, arena
*a
)
169 p
->a
.ops
= &pool_ops
;
175 /* --- @pool_create@ --- *
177 * Arguments: @arena *a@ = pointer to an arena to allocate memory from
179 * Returns: A newly created resource pool.
181 * Use: Creates a resource pool which is not a child of any other
185 pool
*pool_create(arena
*a
)
188 pool
*p
= doalloc(a
, &c
, sizeof(pool
));
194 /* --- @pool_destroy@ --- *
196 * Arguments: @pool *p@ = pointer to pool to destroy
200 * Use: Destroys a pool, freeing all of the resources within it. If
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.
206 void pool_destroy(pool
*p
)
208 pool_resource
*r
, *rr
;
212 /* --- Dispose of all of the resources --- */
223 /* --- Free all of the memory --- *
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.
240 /* --- @pool_add@ --- *
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
248 * Use: Adds a resource to a pool.
251 void pool_add(pool
*p
, pool_resource
*r
, void (*dfn
)(pool_resource
*r
))
256 /* --- @pool_sub@ --- *
258 * Arguments: @pool *p@ = pointer to parent pool
260 * Returns: A new child pool of the parent.
262 * Use: Creates a subpool. The subpool can either be destroyed on
263 * its own, or will be automatically destroyed at the same time
267 typedef struct subpool
{
272 static void subpool_destroy(pool_resource
*r
)
274 subpool
*p
= (subpool
*)r
;
278 pool
*pool_sub(pool
*p
)
280 subpool
*pp
= pool_alloc(p
, sizeof(subpool
));
281 POOL_ADD(p
, &pp
->r
, subpool_destroy
);
282 pp
->p
.a
.ops
= &pool_ops
;
289 /*----- That's all, folks -------------------------------------------------*/