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