01bd8f91114252c1ca04723de7aaed78a38c42e5
[pspp-builds.git] / src / libpspp / pool.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 2000 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17    02110-1301, USA. */
18
19 #include <config.h>
20 #include "pool.h"
21 #include <stdlib.h>
22 #include "alloc.h"
23 #include <libpspp/assertion.h>
24 #include "message.h"
25 #include "size_max.h"
26 #include "str.h"
27
28 /* Fast, low-overhead memory block suballocator. */
29 struct pool
30   {
31     struct pool *parent;        /* Pool of which this pool is a subpool. */
32     struct pool_block *blocks;  /* Blocks owned by the pool. */
33     struct pool_gizmo *gizmos;  /* Other stuff owned by the pool. */
34   };
35
36 /* Pool block. */
37 struct pool_block
38   {
39     struct pool_block *prev;
40     struct pool_block *next;
41     size_t ofs;
42   };
43
44 /* Gizmo types. */
45 enum
46   {
47     POOL_GIZMO_MALLOC,
48     POOL_GIZMO_FILE,
49     POOL_GIZMO_SUBPOOL,
50     POOL_GIZMO_REGISTERED,
51   };
52
53 /* Pool routines can maintain objects (`gizmos') as well as doing
54    suballocation.
55    This structure is used to keep track of them. */
56 struct pool_gizmo
57   {
58     struct pool *pool;
59     struct pool_gizmo *prev;
60     struct pool_gizmo *next;
61
62     long serial;                /* Serial number. */
63     int type;                   /* Type of this gizmo. */
64
65     /* Type-dependent info. */
66     union
67       {
68         FILE *file;             /* POOL_GIZMO_FILE. */
69         struct pool *subpool;   /* POOL_GIZMO_SUBPOOL. */
70
71         /* POOL_GIZMO_REGISTERED. */
72         struct
73           {
74             void (*free) (void *p);
75             void *p;
76           }
77         registered;
78       }
79     p;
80   };
81
82 /* Rounds X up to the next multiple of Y. */
83 #ifndef ROUND_UP
84 #define ROUND_UP(X, Y)                          \
85         (((X) + ((Y) - 1)) / (Y) * (Y))
86 #endif
87
88 /* Types that provide typically useful alignment sizes. */
89 union align
90   {
91     void *op;
92     void (*fp) (void);
93     long l;
94     double d;
95   };
96
97 /* This should be the alignment size used by malloc().  The size of
98    the union above is correct, if not optimal, in all known cases. */
99 #define ALIGN_SIZE sizeof (union align)
100
101 /* DISCRETE_BLOCKS may be declared as nonzero to prevent
102    suballocation of blocks.  This is useful under memory
103    debuggers like valgrind because it allows the source location
104    of bugs to be more accurately pinpointed.
105
106    On the other hand, if we're testing the library, then we want to
107    test the library's real functionality, not its crippled, slow,
108    simplified functionality. */
109 /*#define DISCRETE_BLOCKS 1*/
110
111 /* Size of each block allocated in the pool, in bytes.
112    Should be at least 1k. */
113 #ifndef BLOCK_SIZE
114 #define BLOCK_SIZE 1024
115 #endif
116
117
118 /* Sizes of some structures with alignment padding included. */
119 #define POOL_BLOCK_SIZE ROUND_UP (sizeof (struct pool_block), ALIGN_SIZE)
120 #define POOL_GIZMO_SIZE ROUND_UP (sizeof (struct pool_gizmo), ALIGN_SIZE)
121 #define POOL_SIZE ROUND_UP (sizeof (struct pool), ALIGN_SIZE)
122
123 /* Serial number used to keep track of gizmos for mark/release. */
124 static long serial = 0;
125
126 /* Prototypes. */
127 static void add_gizmo (struct pool *, struct pool_gizmo *);
128 static void free_gizmo (struct pool_gizmo *);
129 static void free_all_gizmos (struct pool *pool);
130 static void delete_gizmo (struct pool *, struct pool_gizmo *);
131 static void check_gizmo (struct pool *, struct pool_gizmo *);
132 \f
133 /* General routines. */
134
135 /* Creates and returns a new memory pool, which allows malloc()'d
136    blocks to be suballocated in a time- and space-efficient manner.
137    The entire contents of the memory pool are freed at once.
138
139    In addition, other objects can be associated with a memory pool.
140    These are released when the pool is destroyed. */
141 struct pool *
142 pool_create (void)
143 {
144   struct pool_block *block;
145   struct pool *pool;
146
147   block = xmalloc (BLOCK_SIZE);
148   block->prev = block->next = block;
149   block->ofs = POOL_BLOCK_SIZE + POOL_SIZE;
150
151   pool = (struct pool *) (((char *) block) + POOL_BLOCK_SIZE);
152   pool->parent = NULL;
153   pool->blocks = block;
154   pool->gizmos = NULL;
155
156   return pool;
157 }
158
159 /* Creates a pool, allocates a block STRUCT_SIZE bytes in
160    length from it, stores the pool's address at offset
161    POOL_MEMBER_OFFSET within the block, and returns the allocated
162    block.
163
164    Meant for use indirectly via pool_create_container(). */
165 void *
166 pool_create_at_offset (size_t struct_size, size_t pool_member_offset)
167 {
168   struct pool *pool;
169   char *struct_;
170
171   assert (struct_size >= sizeof pool);
172   assert (pool_member_offset <= struct_size - sizeof pool);
173
174   pool = pool_create ();
175   struct_ = pool_alloc (pool, struct_size);
176   *(struct pool **) (struct_ + pool_member_offset) = pool;
177   return struct_;
178 }
179
180 /* Destroy the specified pool, including all subpools. */
181 void
182 pool_destroy (struct pool *pool)
183 {
184   if (pool == NULL)
185     return;
186
187   /* Remove this pool from its parent's list of gizmos. */
188   if (pool->parent)
189     delete_gizmo (pool->parent, (void *) (((char *) pool) + POOL_SIZE));
190
191   free_all_gizmos (pool);
192
193   /* Free all the memory. */
194   {
195     struct pool_block *cur, *next;
196
197     pool->blocks->prev->next = NULL;
198     for (cur = pool->blocks; cur; cur = next)
199       {
200         next = cur->next;
201         free (cur);
202       }
203   }
204 }
205
206 /* Release all the memory and gizmos in POOL.
207    Blocks are not given back with free() but kept for later
208    allocations.  To give back memory, use a subpool instead. */
209 void
210 pool_clear (struct pool *pool)
211 {
212   free_all_gizmos (pool);
213
214   /* Zero out block sizes. */
215   {
216     struct pool_block *cur;
217
218     cur = pool->blocks;
219     do
220       {
221         cur->ofs = POOL_BLOCK_SIZE;
222         if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool)
223           {
224             cur->ofs += POOL_SIZE;
225             if (pool->parent != NULL)
226               cur->ofs += POOL_GIZMO_SIZE;
227           }
228         cur = cur->next;
229       }
230     while (cur != pool->blocks);
231   }
232 }
233 \f
234 /* Suballocation routines. */
235
236 /* Allocates a memory region AMT bytes in size from POOL and returns a
237    pointer to the region's start.
238    The region is properly aligned for storing any object. */
239 void *
240 pool_alloc (struct pool *pool, size_t amt)
241 {
242   assert (pool != NULL);
243
244   if (amt == 0)
245     return NULL;
246
247 #ifndef DISCRETE_BLOCKS
248   if (amt <= MAX_SUBALLOC)
249     {
250       /* If there is space in this block, take it. */
251       struct pool_block *b = pool->blocks;
252       b->ofs = ROUND_UP (b->ofs, ALIGN_SIZE);
253       if (b->ofs + amt <= BLOCK_SIZE)
254         {
255           void *const p = ((char *) b) + b->ofs;
256           b->ofs += amt;
257           return p;
258         }
259
260       /* No space in this block, so we must make other
261          arrangements. */
262       if (b->next->ofs == 0)
263         {
264           /* The next block is empty.  Use it. */
265           b = b->next;
266           b->ofs = POOL_BLOCK_SIZE;
267           if ((char *) b + POOL_BLOCK_SIZE == (char *) pool)
268             b->ofs += POOL_SIZE;
269         }
270       else
271         {
272           /* Create a new block at the start of the list. */
273           b = xmalloc (BLOCK_SIZE);
274           b->next = pool->blocks;
275           b->prev = pool->blocks->prev;
276           b->ofs = POOL_BLOCK_SIZE;
277           pool->blocks->prev->next = b;
278           pool->blocks->prev = b;
279         }
280       pool->blocks = b;
281
282       /* Allocate space from B. */
283       b->ofs += amt;
284       return ((char *) b) + b->ofs - amt;
285     }
286   else
287 #endif
288     return pool_malloc (pool, amt);
289 }
290
291 /* Allocates a memory region AMT bytes in size from POOL and
292    returns a pointer to the region's start.  The region is not
293    necessarily aligned, so it is most suitable for storing
294    strings. */
295 void *
296 pool_alloc_unaligned (struct pool *pool, size_t amt)
297 {
298   assert (pool != NULL);
299
300 #ifndef DISCRETE_BLOCKS
301   /* Strings need not be aligned on any boundary, but some
302      operations may be more efficient when they are.  However,
303      that's only going to help with reasonably long strings. */
304   if (amt < ALIGN_SIZE)
305     {
306       if (amt == 0)
307         return NULL;
308       else
309         {
310           struct pool_block *const b = pool->blocks;
311
312           if (b->ofs + amt <= BLOCK_SIZE)
313             {
314               void *p = ((char *) b) + b->ofs;
315               b->ofs += amt;
316               return p;
317             }
318         }
319     }
320 #endif
321
322   return pool_alloc (pool, amt);
323 }
324
325 /* Allocates a memory region N * S bytes in size from POOL and
326    returns a pointer to the region's start.
327    N must be nonnegative, S must be positive.
328    Terminates the program if the memory cannot be obtained,
329    including the case where N * S overflows the range of size_t. */
330 void *
331 pool_nalloc (struct pool *pool, size_t n, size_t s)
332 {
333   if (xalloc_oversized (n, s))
334     xalloc_die ();
335   return pool_alloc (pool, n * s);
336 }
337
338 /* Allocates SIZE bytes in POOL, copies BUFFER into it, and
339    returns the new copy. */
340 void *
341 pool_clone (struct pool *pool, const void *buffer, size_t size)
342 {
343   void *block = pool_alloc (pool, size);
344   memcpy (block, buffer, size);
345   return block;
346 }
347
348 /* Allocates SIZE bytes of unaligned data in POOL, copies BUFFER
349    into it, and returns the new copy. */
350 void *
351 pool_clone_unaligned (struct pool *pool, const void *buffer, size_t size)
352 {
353   void *block = pool_alloc_unaligned (pool, size);
354   memcpy (block, buffer, size);
355   return block;
356 }
357
358 /* Duplicates null-terminated STRING, within POOL, and returns a
359    pointer to the duplicate.  For use only with strings, because
360    the returned pointere may not be aligned properly for other
361    types. */
362 char *
363 pool_strdup (struct pool *pool, const char *string)
364 {
365   return pool_clone_unaligned (pool, string, strlen (string) + 1);
366 }
367
368 /* Formats FORMAT with the given ARGS in memory allocated from
369    POOL and returns the formatted string. */
370 char *
371 pool_vasprintf (struct pool *pool, const char *format, va_list args_)
372 {
373   struct pool_block *b;
374   va_list args;
375   int needed, avail;
376   char *s;
377
378   va_copy (args, args_);
379   b = pool->blocks;
380   avail = BLOCK_SIZE - b->ofs;
381   s = ((char *) b) + b->ofs;
382   needed = vsnprintf (s, avail, format, args);
383   va_end (args);
384
385   if (needed >= 0)
386     {
387       if (needed < avail)
388         {
389           /* Success.  Reserve the space that was actually used. */
390           b->ofs += needed + 1;
391         }
392       else
393         {
394           /* Failure, but now we know how much space is needed.
395              Allocate that much and reformat. */
396           s = pool_alloc (pool, needed + 1);
397
398           va_copy (args, args_);
399           vsprintf (s, format, args);
400           va_end (args);
401         }
402     }
403   else
404     {
405       /* Some old libc's returned -1 when the destination string
406          was too short.  This should be uncommon these days and
407          it's a rare case anyhow.  Use the easiest solution: punt
408          to dynamic allocation. */
409       va_copy (args, args_);
410       s = xvasprintf (format, args);
411       va_end (args);
412
413       pool_register (pool, free, s);
414     }
415
416   return s;
417 }
418
419 /* Formats FORMAT in memory allocated from POOL
420    and returns the formatted string. */
421 char *
422 pool_asprintf (struct pool *pool, const char *format, ...)
423 {
424   va_list args;
425   char *string;
426
427   va_start (args, format);
428   string = pool_vasprintf (pool, format, args);
429   va_end (args);
430
431   return string;
432 }
433 \f
434 /* Standard allocation routines. */
435
436 /* Allocates AMT bytes using malloc(), to be managed by POOL, and
437    returns a pointer to the beginning of the block.
438    If POOL is a null pointer, then allocates a normal memory block
439    with xmalloc().  */
440 void *
441 pool_malloc (struct pool *pool, size_t amt)
442 {
443   if (pool != NULL)
444     {
445       if (amt != 0)
446         {
447           struct pool_gizmo *g = xmalloc (amt + POOL_GIZMO_SIZE);
448           g->type = POOL_GIZMO_MALLOC;
449           add_gizmo (pool, g);
450
451           return ((char *) g) + POOL_GIZMO_SIZE;
452         }
453       else
454         return NULL;
455     }
456   else
457     return xmalloc (amt);
458 }
459
460 /* Allocates and returns N elements of S bytes each, to be
461    managed by POOL.
462    If POOL is a null pointer, then allocates a normal memory block
463    with malloc().
464    N must be nonnegative, S must be positive.
465    Terminates the program if the memory cannot be obtained,
466    including the case where N * S overflows the range of size_t. */
467 void *
468 pool_nmalloc (struct pool *pool, size_t n, size_t s)
469 {
470   if (xalloc_oversized (n, s))
471     xalloc_die ();
472   return pool_malloc (pool, n * s);
473 }
474
475 /* Allocates AMT bytes using malloc(), to be managed by POOL,
476    zeros the block, and returns a pointer to the beginning of the
477    block.
478    If POOL is a null pointer, then allocates a normal memory block
479    with xmalloc().  */
480 void *
481 pool_zalloc (struct pool *pool, size_t amt)
482 {
483   void *p = pool_malloc (pool, amt);
484   memset (p, 0, amt);
485   return p;
486 }
487
488 /* Allocates and returns N elements of S bytes each, to be
489    managed by POOL, and zeros the block.
490    If POOL is a null pointer, then allocates a normal memory block
491    with malloc().
492    N must be nonnegative, S must be positive.
493    Terminates the program if the memory cannot be obtained,
494    including the case where N * S overflows the range of size_t. */
495 void *
496 pool_calloc (struct pool *pool, size_t n, size_t s)
497 {
498   void *p = pool_nmalloc (pool, n, s);
499   memset (p, 0, n * s);
500   return p;
501 }
502
503 /* Changes the allocation size of the specified memory block P managed
504    by POOL to AMT bytes and returns a pointer to the beginning of the
505    block.
506    If POOL is a null pointer, then the block is reallocated in the
507    usual way with realloc(). */
508 void *
509 pool_realloc (struct pool *pool, void *p, size_t amt)
510 {
511   if (pool != NULL)
512     {
513       if (p != NULL)
514         {
515           if (amt != 0)
516             {
517               struct pool_gizmo *g = (void *) (((char *) p) - POOL_GIZMO_SIZE);
518               check_gizmo (pool, g);
519
520               g = xrealloc (g, amt + POOL_GIZMO_SIZE);
521               if (g->next)
522                 g->next->prev = g;
523               if (g->prev)
524                 g->prev->next = g;
525               else
526                 pool->gizmos = g;
527               check_gizmo (pool, g);
528
529               return ((char *) g) + POOL_GIZMO_SIZE;
530             }
531           else
532             {
533               pool_free (pool, p);
534               return NULL;
535             }
536         }
537       else
538         return pool_malloc (pool, amt);
539     }
540   else
541     return xrealloc (p, amt);
542 }
543
544 /* Changes the allocation size of the specified memory block P
545    managed by POOL to N * S bytes and returns a pointer to the
546    beginning of the block.
547    N must be nonnegative, S must be positive.
548    If POOL is a null pointer, then the block is reallocated in
549    the usual way with xrealloc().
550    Terminates the program if the memory cannot be obtained,
551    including the case where N * S overflows the range of size_t. */
552 void *
553 pool_nrealloc (struct pool *pool, void *p, size_t n, size_t s)
554 {
555   if (xalloc_oversized (n, s))
556     xalloc_die ();
557   return pool_realloc (pool, p, n * s);
558 }
559
560 /* If P is null, allocate a block of at least *PN such objects;
561    otherwise, reallocate P so that it contains more than *PN
562    objects each of S bytes.  *PN must be nonzero unless P is
563    null, and S must be nonzero.  Set *PN to the new number of
564    objects, and return the pointer to the new block.  *PN is
565    never set to zero, and the returned pointer is never null.
566
567    The block returned is managed by POOL.  If POOL is a null
568    pointer, then the block is reallocated in the usual way with
569    x2nrealloc().
570
571    Terminates the program if the memory cannot be obtained,
572    including the case where the memory required overflows the
573    range of size_t.
574
575    Repeated reallocations are guaranteed to make progress, either by
576    allocating an initial block with a nonzero size, or by allocating a
577    larger block.
578
579    In the following implementation, nonzero sizes are doubled so that
580    repeated reallocations have O(N log N) overall cost rather than
581    O(N**2) cost, but the specification for this function does not
582    guarantee that sizes are doubled.
583
584    Here is an example of use:
585
586      int *p = NULL;
587      struct pool *pool;
588      size_t used = 0;
589      size_t allocated = 0;
590
591      void
592      append_int (int value)
593        {
594          if (used == allocated)
595            p = pool_2nrealloc (pool, p, &allocated, sizeof *p);
596          p[used++] = value;
597        }
598
599    This causes x2nrealloc to allocate a block of some nonzero size the
600    first time it is called.
601
602    To have finer-grained control over the initial size, set *PN to a
603    nonzero value before calling this function with P == NULL.  For
604    example:
605
606      int *p = NULL;
607      struct pool *pool;
608      size_t used = 0;
609      size_t allocated = 0;
610      size_t allocated1 = 1000;
611
612      void
613      append_int (int value)
614        {
615          if (used == allocated)
616            {
617              p = pool_2nrealloc (pool, p, &allocated1, sizeof *p);
618              allocated = allocated1;
619            }
620          p[used++] = value;
621        }
622
623    This function implementation is from gnulib. */
624 void *
625 pool_2nrealloc (struct pool *pool, void *p, size_t *pn, size_t s)
626 {
627   size_t n = *pn;
628
629   if (p == NULL)
630     {
631       if (n == 0)
632         {
633           /* The approximate size to use for initial small allocation
634              requests, when the invoking code specifies an old size of
635              zero.  64 bytes is the largest "small" request for the
636              GNU C library malloc.  */
637           enum { DEFAULT_MXFAST = 64 };
638
639           n = DEFAULT_MXFAST / s;
640           n += !n;
641         }
642     }
643   else
644     {
645       if (SIZE_MAX / 2 / s < n)
646         xalloc_die ();
647       n *= 2;
648     }
649
650   *pn = n;
651   return pool_realloc (pool, p, n * s);
652 }
653
654 /* Frees block P managed by POOL.
655    If POOL is a null pointer, then the block is freed as usual with
656    free(). */
657 void
658 pool_free (struct pool *pool, void *p)
659 {
660   if (pool != NULL && p != NULL)
661     {
662       struct pool_gizmo *g = (void *) (((char *) p) - POOL_GIZMO_SIZE);
663       check_gizmo (pool, g);
664       delete_gizmo (pool, g);
665       free (g);
666     }
667   else
668     free (p);
669 }
670 \f
671 /* Gizmo allocations. */
672
673 /* Creates and returns a pool as a subpool of POOL.
674    The subpool will be destroyed automatically when POOL is destroyed.
675    It may also be destroyed explicitly in advance. */
676 struct pool *
677 pool_create_subpool (struct pool *pool)
678 {
679   struct pool *subpool;
680   struct pool_gizmo *g;
681
682   assert (pool != NULL);
683   subpool = pool_create ();
684   subpool->parent = pool;
685
686   g = (void *) (((char *) subpool->blocks) + subpool->blocks->ofs);
687   subpool->blocks->ofs += POOL_GIZMO_SIZE;
688
689   g->type = POOL_GIZMO_SUBPOOL;
690   g->p.subpool = subpool;
691
692   add_gizmo (pool, g);
693
694   return subpool;
695 }
696
697 /* Makes SUBPOOL a subpool of POOL.
698    SUBPOOL must not already have a parent pool.
699    The subpool will be destroyed automatically when POOL is destroyed.
700    It may also be destroyed explicitly in advance. */
701 void
702 pool_add_subpool (struct pool *pool, struct pool *subpool)
703 {
704   struct pool_gizmo *g;
705
706   assert (pool != NULL);
707   assert (subpool != NULL);
708   assert (subpool->parent == NULL);
709
710   g = pool_alloc (subpool, sizeof *g);
711   g->type = POOL_GIZMO_SUBPOOL;
712   g->p.subpool = subpool;
713   add_gizmo (pool, g);
714
715   subpool->parent = pool;
716 }
717
718 /* Opens file FILE_NAME with mode MODE and returns a handle to it
719    if successful or a null pointer if not.
720    The file will be closed automatically when POOL is destroyed, or it
721    may be closed explicitly in advance using pool_fclose(), or
722    detached from the pool with pool_detach_file(). */
723 FILE *
724 pool_fopen (struct pool *pool, const char *file_name, const char *mode)
725 {
726   FILE *f;
727
728   assert (pool && file_name && mode);
729   f = fopen (file_name, mode);
730   if (f != NULL)
731     pool_attach_file (pool, f);
732
733   return f;
734 }
735
736 /* Closes file FILE managed by POOL.
737    Returns 0 if successful, EOF if an I/O error occurred. */
738 int
739 pool_fclose (struct pool *pool, FILE *file)
740 {
741   assert (pool && file);
742   pool_detach_file (pool, file);
743   return fclose (file);
744 }
745
746 /* Creates a temporary file with tmpfile() and returns a handle to it
747    if successful or a null pointer if not.
748    The file will be closed automatically when POOL is destroyed, or it
749    may be closed explicitly in advance using pool_fclose(), or
750    detached from the pool with pool_detach_file(). */
751 FILE *
752 pool_tmpfile (struct pool *pool)
753 {
754   FILE *file = tmpfile ();
755   if (file != NULL)
756     pool_attach_file (pool, file);
757   return file;
758 }
759
760 /* Attaches FILE to POOL.
761    The file will be closed automatically when POOL is destroyed, or it
762    may be closed explicitly in advance using pool_fclose(), or
763    detached from the pool with pool_detach_file(). */
764 void
765 pool_attach_file (struct pool *pool, FILE *file)
766 {
767   struct pool_gizmo *g = pool_alloc (pool, sizeof *g);
768   g->type = POOL_GIZMO_FILE;
769   g->p.file = file;
770   add_gizmo (pool, g);
771 }
772
773 /* Detaches FILE from POOL. */
774 void
775 pool_detach_file (struct pool *pool, FILE *file)
776 {
777   struct pool_gizmo *g;
778
779   for (g = pool->gizmos; g; g = g->next)
780     if (g->type == POOL_GIZMO_FILE && g->p.file == file)
781       {
782         delete_gizmo (pool, g);
783         return;
784       }
785 }
786 \f
787 /* Registers FREE to be called with argument P.
788    P should be unique among those registered in POOL so that it can be
789    uniquely identified by pool_unregister().
790    If not unregistered, FREE will be called with argument P when POOL
791    is destroyed. */
792 void
793 pool_register (struct pool *pool, void (*free) (void *), void *p)
794 {
795   assert (pool && free && p);
796
797   {
798     struct pool_gizmo *g = pool_alloc (pool, sizeof *g);
799     g->type = POOL_GIZMO_REGISTERED;
800     g->p.registered.free = free;
801     g->p.registered.p = p;
802     add_gizmo (pool, g);
803   }
804 }
805
806 /* Unregisters previously registered P from POOL.
807    Returns true only if P was found to be registered in POOL. */
808 bool
809 pool_unregister (struct pool *pool, void *p)
810 {
811   assert (pool && p);
812
813   {
814     struct pool_gizmo *g;
815
816     for (g = pool->gizmos; g; g = g->next)
817       if (g->type == POOL_GIZMO_REGISTERED && g->p.registered.p == p)
818         {
819           delete_gizmo (pool, g);
820           return true;
821         }
822   }
823
824   return false;
825 }
826 \f
827 /* Partial freeing. */
828
829 /* Notes the state of POOL into MARK so that it may be restored
830    by a call to pool_release(). */
831 void
832 pool_mark (struct pool *pool, struct pool_mark *mark)
833 {
834   assert (pool && mark);
835
836   mark->block = pool->blocks;
837   mark->ofs = pool->blocks->ofs;
838
839   mark->serial = serial;
840 }
841
842 /* Restores to POOL the state recorded in MARK.
843    Emptied blocks are not given back with free() but kept for
844    later allocations.  To get that behavior, use a subpool
845    instead. */
846 void
847 pool_release (struct pool *pool, const struct pool_mark *mark)
848 {
849   assert (pool && mark);
850
851   {
852     struct pool_gizmo *cur, *next;
853
854     for (cur = pool->gizmos; cur && cur->serial >= mark->serial; cur = next)
855       {
856         next = cur->next;
857         free_gizmo (cur);
858       }
859
860     if (cur != NULL)
861       {
862         cur->prev = NULL;
863         pool->gizmos = cur;
864       }
865     else
866       pool->gizmos = NULL;
867   }
868
869   {
870     struct pool_block *cur;
871
872     for (cur = pool->blocks; cur != mark->block; cur = cur->next)
873       {
874         cur->ofs = POOL_BLOCK_SIZE;
875         if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool)
876           {
877             cur->ofs += POOL_SIZE;
878             if (pool->parent != NULL)
879               cur->ofs += POOL_GIZMO_SIZE;
880           }
881       }
882     pool->blocks = mark->block;
883     pool->blocks->ofs = mark->ofs;
884   }
885 }
886 \f
887 /* Private functions. */
888
889 /* Adds GIZMO at the beginning of POOL's gizmo list. */
890 static void
891 add_gizmo (struct pool *pool, struct pool_gizmo *gizmo)
892 {
893   assert (pool && gizmo);
894
895   gizmo->pool = pool;
896   gizmo->next = pool->gizmos;
897   gizmo->prev = NULL;
898   if (pool->gizmos)
899     pool->gizmos->prev = gizmo;
900   pool->gizmos = gizmo;
901
902   gizmo->serial = serial++;
903
904   check_gizmo (pool, gizmo);
905 }
906
907 /* Removes GIZMO from POOL's gizmo list. */
908 static void
909 delete_gizmo (struct pool *pool, struct pool_gizmo *gizmo)
910 {
911   assert (pool && gizmo);
912
913   check_gizmo (pool, gizmo);
914
915   if (gizmo->prev)
916     gizmo->prev->next = gizmo->next;
917   else
918     pool->gizmos = gizmo->next;
919   if (gizmo->next)
920     gizmo->next->prev = gizmo->prev;
921 }
922
923 /* Frees any of GIZMO's internal state.
924    GIZMO's data must not be referenced after calling this function. */
925 static void
926 free_gizmo (struct pool_gizmo *gizmo)
927 {
928   assert (gizmo != NULL);
929
930   switch (gizmo->type)
931     {
932     case POOL_GIZMO_MALLOC:
933       free (gizmo);
934       break;
935     case POOL_GIZMO_FILE:
936       fclose (gizmo->p.file);   /* Ignore errors. */
937       break;
938     case POOL_GIZMO_SUBPOOL:
939       gizmo->p.subpool->parent = NULL;
940       pool_destroy (gizmo->p.subpool);
941       break;
942     case POOL_GIZMO_REGISTERED:
943       gizmo->p.registered.free (gizmo->p.registered.p);
944       break;
945     default:
946       NOT_REACHED ();
947     }
948 }
949
950 /* Free all the gizmos in POOL. */
951 static void
952 free_all_gizmos (struct pool *pool)
953 {
954   struct pool_gizmo *cur, *next;
955
956   for (cur = pool->gizmos; cur; cur = next)
957     {
958       next = cur->next;
959       free_gizmo (cur);
960     }
961   pool->gizmos = NULL;
962 }
963
964 static void
965 check_gizmo (struct pool *p, struct pool_gizmo *g)
966 {
967   assert (g->pool == p);
968   assert (g->next == NULL || g->next->prev == g);
969   assert ((g->prev != NULL && g->prev->next == g)
970           || (g->prev == NULL && p->gizmos == g));
971
972 }