chiark / gitweb /
@@@ pool upgrade
[mLib] / mem / pool.h
1 /* -*-c-*-
2  *
3  * Resource pool handling
4  *
5  * (c) 2000 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the mLib utilities library.
11  *
12  * mLib is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * mLib is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with mLib; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 #ifndef MLIB_POOL_H
29 #define MLIB_POOL_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <stdio.h>
38
39 #ifndef MLIB_ARENA_H
40 #  include "arena.h"
41 #endif
42
43 #ifndef MLIB_SUB_H
44 #  include "sub.h"
45 #endif
46
47 /*----- Data structures ---------------------------------------------------*/
48
49 #define POOL_CHUNKSZ 65536
50
51 typedef struct pool_chunk {
52   unsigned char *p;                     /* Free area in this chunk */
53   union {
54     size_t sz;                          /* Amount of memory left */
55     struct pool_chunk *next;            /* Link to next dead chunk */
56   } u;
57 } pool_chunk;
58
59 typedef struct pool_resource {
60   struct pool_resource *next;           /* Next resource in the chain */
61   void (*destroy)(struct pool_resource */*r*/); /* Destruction function */
62 } pool_resource;
63
64 typedef struct pool {
65   arena a;                              /* The arena for allocating memory */
66   pool_chunk *active;                   /* Most recent memory chunk */
67   pool_resource *resources;             /* Head of resource list */
68   arena *pa;                            /* Arena for real allocation */
69   unsigned f;                           /* Flags */
70 #define PF_VALGRIND 1u                  /*   Special Valgrind hacks active */
71 #define PF_SUBPOOL 2u                   /*   Pool is a subpool */
72   size_t lastsz;                        /* Size of most recent allocation */
73   pool_chunk **live;                    /* Chunks, max-heap by space left */
74   size_t nlive;                         /* Number of chunks in the heap */
75   size_t livesz;                        /* Allocated size of heap vector */
76   pool_chunk *dead;                     /* List of dead chunks */
77 } pool;
78
79 typedef struct pool_file {
80   pool_resource r;                      /* A pool resource record */
81   FILE *fp;                             /* The actual file handle */
82 } pool_file;
83
84 /*----- Basic pool management ---------------------------------------------*/
85
86 /* --- @pool_create@ --- *
87  *
88  * Arguments:   @arena *a@ = pointer to an arena to allocate memory from
89  *
90  * Returns:     A newly created resource pool.
91  *
92  * Use:         Creates a fresh root resource pool, i.e., one  which is not a
93  *              child of any other pool.
94  */
95
96 extern pool *pool_create(arena */*a*/);
97
98 /* --- @pool_sub@ --- *
99  *
100  * Arguments:   @pool *p@ = pointer to parent pool
101  *
102  * Returns:     A new child pool of the parent.
103  *
104  * Use:         Creates a subpool.  The subpool can either be destroyed on
105  *              its own, or will be automatically destroyed at the same time
106  *              as the parent.
107  */
108
109 extern pool *pool_sub(pool */*p*/);
110
111 /* --- @pool_alloc@, @pool_allocv@ --- *
112  *
113  * Arguments:   @pool *p@ = pool to allocate from
114  *              @size_t n@ = number of elements to allocate (for
115  *                      @pool_allocv@)
116  *              @size_t sz@ = size of block wanted
117  *
118  * Returns:     Pointer to the requested block.
119  *
120  * Use:         The @pool_allocv@ function allocates memory for @n@ elements
121  *              of @sz@ bytes each from a resource pool.  Only the most
122  *              recent allocation can usefully be adjusted and/or freed;
123  *              other allocations persist until the pool is destroyed.  The
124  *              @pool_alloc@ function is the same, but with @n@ fixed equal
125  *              to 1.  If there's not enough memory, the exception
126  *              @EXC_NOMEM@ is thrown.
127  */
128
129 extern void *pool_alloc(pool */*p*/, size_t /*sz*/);
130 void *pool_allocv(pool */*p*/, size_t /*n*/, size_t /*sz*/);
131
132 /* --- @POOL_NEW@, @POOL_NEWV@ --- *
133  *
134  * Arguments:   @type *q@ = pointer to allocate
135  *              @pool *p@ = pool to allocate from
136  *              @size_t n@ = number of elements to allocate (for @POOL_NEWV@)
137  *
138  * Returns:     ---
139  *
140  * Use:         The @POOL_NEW@ macro sets @p@ to point to a freshly allocated
141  *              block of memory large enough for an object of the type
142  *              pointed to by @p@.  The @POOL_NEWV@ macro allocated enough
143  *              space for a vector of @n@ elements, each of the type pointed
144  *              to by @p@.  If there is not enough memory, the exception
145  *              @EXC_NOMEM@ is thrown.
146  */
147
148 #define POOL_NEW(q, p) do { (q) = pool_alloc((p), sizeof(*(q))); } while (0)
149 #define POOL_NEWV(q, p, n)                                              \
150         do { (q) = pool_allocv((p), (n), sizeof(*(q))); } while (0)
151
152 /* --- @pool_realloc@, @pool_reallocv@ --- *
153  *
154  * Arguments:   @pool *p@ = pointer to the pool
155  *              @void *q@ = pointer to block
156  *              @size_t n@ = new number of elements (for @pool_reallocv@)
157  *              @size_t on@ = old number of elements (for @pool_reallocv@)
158  *              @size_t sz@ = size of elements (for @pool_reallocv@)
159  *              @size_t newsz@ = the new size required (for @pool_realloc@)
160  *              @size_t oldsz@ = existing size allocated (for @pool_realloc@)
161  *
162  * Returns:     The new address of the block.
163  *
164  * Use:         The @pool_reallocv@ function returns a pointer to a block of
165  *              memory, large enough for @n@ elements each of size @sz@,
166  *              containing a copy of the first @min(n, on)@ elements
167  *              currently in the block at @q@.  If the new pointer is not
168  *              equal to @q@, then @q@ is invalidated and it is an error to
169  *              make further use of it.
170  *
171  *              If @q@ points to the most recently allocated block, then the
172  *              old storage is reclaimed.  Otherwise, if @n@ is smaller than
173  *              @on@, the block is shrunk in place, but the excess space is
174  *              lost until the pool is destroyed.  Otherwise, a fresh block
175  *              is allocated and the data copied, and the old block's space
176  *              is lost until the pool is destroyed.
177  *
178  *              The @pool_realloc@ function is the same, except that @sz@ is
179  *              fixed at 1, and @n@ and @on@ are renamed to @newsz@ and
180  *              @oldsz@.
181  */
182
183 extern void *pool_realloc(pool */*p*/, void */*q*/,
184                           size_t /*newsz*/, size_t /*oldsz*/);
185 extern void *pool_reallocv(pool */*p*/, void */*q*/,
186                            size_t /*n*/, size_t /*on*/, size_t /*sz*/);
187
188 /* --- @POOL_RENEWV@ --- *
189  *
190  * Arguments:   @type *q@ = a pointer to allocate
191  *              @pool *q@ = pointer to pool
192  *              @size_t n, on@ = new and existing numbers of elements
193  *
194  * Returns:     ---
195  *
196  * Use:         Adjust @p@ to point to a new block of memory with space for
197  *              @n@ elements of the type pointed to by @p@, on the assumption
198  *              that @p@ is either null or currently points to a block with
199  *              space for @on@ elements.
200  */
201
202 #define POOL_RENEWV(q, p, n, on)                                        \
203         do { (q) = pool_reallocv((p), (n), (on), sizeof(*(q))); while (0)
204
205 /* --- @pool_strdup@ --- *
206  *
207  * Arguments:   @pool *p@ = pool to allocate from
208  *              @const char *s@ = pointer to string
209  *
210  * Returns:     A pointer to a copy of the string.
211  *
212  * Use:         Allocates a copy of a string.
213  */
214
215 extern char *pool_strdup(pool */*p*/, const char */*s*/);
216
217 /* --- @pool_free@ --- *
218  *
219  * Arguments:   @pool *p@ = pointer to the pool
220  *              @void *q@ = pointer to block
221  *
222  * Returns:     ---
223  *
224  * Use:         Try to recycle the memory used by the block allocated at @q@.
225  *              If @q@ points to the most recently allocated block, then it
226  *              can be reclaimed at no cost.  Otherwise, the allocation
227  *              persists anyway until the pool as a whole is destroyed --
228  *              though the pointer is logically invalidated, and it is an
229  *              error to make further use of it.
230  */
231
232 extern void pool_free(pool */*p*/, void */*q*/);
233
234 /* --- @pool_recycle@ --- *
235  *
236  * Arguments:   @pool *p@ = pointer to the pool
237  *
238  * Returns:     ---
239  *
240  * Use:         Release all of the memory and resources held by the pool,
241  *              with the expectation that it will be used again.  The chunks
242  *              from which allocations were satisfied are retained for future
243  *              use.
244  */
245
246 extern void pool_recycle(pool */*p*/);
247
248 /* --- @pool_destroy@ --- *
249  *
250  * Arguments:   @pool *p@ = pointer to pool to destroy
251  *
252  * Returns:     ---
253  *
254  * Use:         Destroys a pool, freeing all of the resources within it.  If
255  *              this is a root pool, its memory will be deallocated; if it's
256  *              a subpool, it is emptied and can be used again.
257  */
258
259 extern void pool_destroy(pool */*p*/);
260
261 /* --- @pool_add@, @POOL_ADD@ --- *
262  *
263  * Arguments:   @pool *p@ = pointer to pool to add the resource to
264  *              @pool_resource *r@ = pointer to resource block
265  *              @void (*dfn)(pool_resource *r)@ = destruction function
266  *
267  * Returns:     ---
268  *
269  * Use:         Adds a resource to a pool.
270  */
271
272 #define POOL_ADD(p, rr, dfn) do {                                       \
273   pool *_p = (p);                                                       \
274   pool_resource *_r = (rr);                                             \
275                                                                         \
276   _r->next = _p->resources;                                             \
277   _r->destroy = dfn;                                                    \
278   _p->resources = _r;                                                   \
279 } while (0)
280
281 extern void pool_add(pool */*p*/, pool_resource */*r*/,
282                      void (*/*dfn*/)(pool_resource */*r*/));
283
284 /*----- Various simple resource types -------------------------------------*/
285
286 /* --- @pool_fopen@ --- *
287  *
288  * Arguments:   @pool *p@ = pointer to a pool
289  *              @const char *file@ = name of the file to open
290  *              @const char *how@ = string specifying opening parameters
291  *
292  * Returns:     A pointer to a pool resource containing an open file handle,
293  *              or null if the file open filed.
294  *
295  * Use:         Opens a file so that it will be freed again when a pool is
296  *              destroyed.
297  */
298
299 extern pool_file *pool_fopen(pool */*p*/,
300                              const char */*file*/, const char */*how*/);
301
302 /* --- @pool_fclose@ --- *
303  *
304  * Arguments:   @pool_file *pf@ = pointer to a file resource
305  *
306  * Returns:     The response from the @fclose@ function.
307  *
308  * Use:         Closes a file.  It is not an error to close a file multiple
309  *              times.
310  */
311
312 extern int pool_fclose(pool_file */*pf*/);
313
314 /* --- @pool_subarena@ --- *
315  *
316  * Arguments:   @pool *p@ = pointer to the pool
317  *
318  * Returns:     A subarena built from the pool's memory allocator.
319  *
320  * Use:         Creates a suballocation arena attached to a pool.  The arena
321  *              and all of its memory will be freed when the pool is
322  *              destroyed.
323  */
324
325 extern subarena *pool_subarena(pool */*p*/);
326
327 /*----- That's all, folks -------------------------------------------------*/
328
329 #ifdef __cplusplus
330   }
331 #endif
332
333 #endif