105937b99885262c2e8d0ec609f61bc471f09087
[pspp-builds.git] / src / libpspp / pool.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 2000 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301, USA. */
19
20 #include <config.h>
21 #include "pool.h"
22 #include <stdlib.h>
23 #include "alloc.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 Checker or valgrind because it allows the
104    source location 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 \f
368 /* Standard allocation routines. */
369
370 /* Allocates AMT bytes using malloc(), to be managed by POOL, and
371    returns a pointer to the beginning of the block.
372    If POOL is a null pointer, then allocates a normal memory block
373    with xmalloc().  */
374 void *
375 pool_malloc (struct pool *pool, size_t amt)
376 {
377   if (pool != NULL)
378     {
379       if (amt != 0)
380         {
381           struct pool_gizmo *g = xmalloc (amt + POOL_GIZMO_SIZE);
382           g->type = POOL_GIZMO_MALLOC;
383           add_gizmo (pool, g);
384
385           return ((char *) g) + POOL_GIZMO_SIZE;
386         }
387       else
388         return NULL;
389     }
390   else
391     return xmalloc (amt);
392 }
393
394 /* Allocates and returns N elements of S bytes each, to be
395    managed by POOL.
396    If POOL is a null pointer, then allocates a normal memory block
397    with malloc().
398    N must be nonnegative, S must be positive.
399    Terminates the program if the memory cannot be obtained,
400    including the case where N * S overflows the range of size_t. */
401 void *
402 pool_nmalloc (struct pool *pool, size_t n, size_t s) 
403 {
404   if (xalloc_oversized (n, s))
405     xalloc_die ();
406   return pool_malloc (pool, n * s);
407 }
408
409 /* Changes the allocation size of the specified memory block P managed
410    by POOL to AMT bytes and returns a pointer to the beginning of the
411    block.
412    If POOL is a null pointer, then the block is reallocated in the
413    usual way with realloc(). */
414 void *
415 pool_realloc (struct pool *pool, void *p, size_t amt)
416 {
417   if (pool != NULL)
418     {
419       if (p != NULL)
420         {
421           if (amt != 0)
422             {
423               struct pool_gizmo *g = (void *) (((char *) p) - POOL_GIZMO_SIZE);
424               check_gizmo (pool, g);
425
426               g = xrealloc (g, amt + POOL_GIZMO_SIZE);
427               if (g->next)
428                 g->next->prev = g;
429               if (g->prev)
430                 g->prev->next = g;
431               else
432                 pool->gizmos = g;
433               check_gizmo (pool, g);
434
435               return ((char *) g) + POOL_GIZMO_SIZE;
436             }
437           else
438             {
439               pool_free (pool, p);
440               return NULL;
441             }
442         }
443       else
444         return pool_malloc (pool, amt);
445     }
446   else
447     return xrealloc (p, amt);
448 }
449
450 /* Changes the allocation size of the specified memory block P
451    managed by POOL to N * S bytes and returns a pointer to the
452    beginning of the block.
453    N must be nonnegative, S must be positive.
454    If POOL is a null pointer, then the block is reallocated in
455    the usual way with xrealloc().
456    Terminates the program if the memory cannot be obtained,
457    including the case where N * S overflows the range of size_t. */
458 void *
459 pool_nrealloc (struct pool *pool, void *p, size_t n, size_t s)
460 {
461   if (xalloc_oversized (n, s))
462     xalloc_die ();
463   return pool_realloc (pool, p, n * s);
464 }
465
466 /* If P is null, allocate a block of at least *PN such objects;
467    otherwise, reallocate P so that it contains more than *PN
468    objects each of S bytes.  *PN must be nonzero unless P is
469    null, and S must be nonzero.  Set *PN to the new number of
470    objects, and return the pointer to the new block.  *PN is
471    never set to zero, and the returned pointer is never null.
472
473    The block returned is managed by POOL.  If POOL is a null
474    pointer, then the block is reallocated in the usual way with
475    x2nrealloc().
476
477    Terminates the program if the memory cannot be obtained,
478    including the case where the memory required overflows the
479    range of size_t.
480
481    Repeated reallocations are guaranteed to make progress, either by
482    allocating an initial block with a nonzero size, or by allocating a
483    larger block.
484
485    In the following implementation, nonzero sizes are doubled so that
486    repeated reallocations have O(N log N) overall cost rather than
487    O(N**2) cost, but the specification for this function does not
488    guarantee that sizes are doubled.
489
490    Here is an example of use:
491
492      int *p = NULL;
493      struct pool *pool;
494      size_t used = 0;
495      size_t allocated = 0;
496
497      void
498      append_int (int value)
499        {
500          if (used == allocated)
501            p = pool_2nrealloc (pool, p, &allocated, sizeof *p);
502          p[used++] = value;
503        }
504
505    This causes x2nrealloc to allocate a block of some nonzero size the
506    first time it is called.
507
508    To have finer-grained control over the initial size, set *PN to a
509    nonzero value before calling this function with P == NULL.  For
510    example:
511
512      int *p = NULL;
513      struct pool *pool;
514      size_t used = 0;
515      size_t allocated = 0;
516      size_t allocated1 = 1000;
517
518      void
519      append_int (int value)
520        {
521          if (used == allocated)
522            {
523              p = pool_2nrealloc (pool, p, &allocated1, sizeof *p);
524              allocated = allocated1;
525            }
526          p[used++] = value;
527        }
528
529    This function implementation is from gnulib. */
530 void *
531 pool_2nrealloc (struct pool *pool, void *p, size_t *pn, size_t s)
532 {
533   size_t n = *pn;
534
535   if (p == NULL)
536     {
537       if (n == 0)
538         {
539           /* The approximate size to use for initial small allocation
540              requests, when the invoking code specifies an old size of
541              zero.  64 bytes is the largest "small" request for the
542              GNU C library malloc.  */
543           enum { DEFAULT_MXFAST = 64 };
544
545           n = DEFAULT_MXFAST / s;
546           n += !n;
547         }
548     }
549   else
550     {
551       if (SIZE_MAX / 2 / s < n)
552         xalloc_die ();
553       n *= 2;
554     }
555
556   *pn = n;
557   return pool_realloc (pool, p, n * s);
558 }
559
560 /* Frees block P managed by POOL.
561    If POOL is a null pointer, then the block is freed as usual with
562    free(). */
563 void
564 pool_free (struct pool *pool, void *p)
565 {
566   if (pool != NULL && p != NULL)
567     {
568       struct pool_gizmo *g = (void *) (((char *) p) - POOL_GIZMO_SIZE);
569       check_gizmo (pool, g);
570       delete_gizmo (pool, g);
571       free (g);
572     }
573   else
574     free (p);
575 }
576 \f
577 /* Gizmo allocations. */
578
579 /* Creates and returns a pool as a subpool of POOL.
580    The subpool will be destroyed automatically when POOL is destroyed.
581    It may also be destroyed explicitly in advance. */
582 struct pool *
583 pool_create_subpool (struct pool *pool)
584 {
585   struct pool *subpool;
586   struct pool_gizmo *g;
587
588   assert (pool != NULL);
589   subpool = pool_create ();
590   subpool->parent = pool;
591
592   g = (void *) (((char *) subpool->blocks) + subpool->blocks->ofs);
593   subpool->blocks->ofs += POOL_GIZMO_SIZE;
594   
595   g->type = POOL_GIZMO_SUBPOOL;
596   g->p.subpool = subpool;
597
598   add_gizmo (pool, g);
599
600   return subpool;
601 }
602
603 /* Makes SUBPOOL a subpool of POOL.
604    SUBPOOL must not already have a parent pool.
605    The subpool will be destroyed automatically when POOL is destroyed.
606    It may also be destroyed explicitly in advance. */
607 void
608 pool_add_subpool (struct pool *pool, struct pool *subpool) 
609 {
610   struct pool_gizmo *g;
611
612   assert (pool != NULL);
613   assert (subpool != NULL);
614   assert (subpool->parent == NULL);
615   
616   g = pool_alloc (subpool, sizeof *g);
617   g->type = POOL_GIZMO_SUBPOOL;
618   g->p.subpool = subpool;
619   add_gizmo (pool, g);
620
621   subpool->parent = pool;
622 }
623
624 /* Opens file FILENAME with mode MODE and returns a handle to it
625    if successful or a null pointer if not.
626    The file will be closed automatically when POOL is destroyed, or it
627    may be closed explicitly in advance using pool_fclose(), or
628    detached from the pool with pool_detach_file(). */
629 FILE *
630 pool_fopen (struct pool *pool, const char *filename, const char *mode)
631 {
632   FILE *f;
633
634   assert (pool && filename && mode);
635   f = fopen (filename, mode);
636   if (f == NULL)
637     return NULL;
638
639   return f;
640 }
641
642 /* Closes file FILE managed by POOL.
643    Returns 0 if successful, EOF if an I/O error occurred. */
644 int
645 pool_fclose (struct pool *pool, FILE *file)
646 {
647   assert (pool && file);
648   pool_detach_file (pool, file);
649   return fclose (file);
650 }
651
652 /* Creates a temporary file with tmpfile() and returns a handle to it
653    if successful or a null pointer if not.
654    The file will be closed automatically when POOL is destroyed, or it
655    may be closed explicitly in advance using pool_fclose(), or
656    detached from the pool with pool_detach_file(). */
657 FILE *
658 pool_tmpfile (struct pool *pool) 
659 {
660   FILE *file = tmpfile ();
661   if (file != NULL)
662     pool_attach_file (pool, file);
663   return file;
664 }
665
666 /* Attaches FILE to POOL.
667    The file will be closed automatically when POOL is destroyed, or it
668    may be closed explicitly in advance using pool_fclose(), or
669    detached from the pool with pool_detach_file(). */
670 void
671 pool_attach_file (struct pool *pool, FILE *file)
672 {
673   struct pool_gizmo *g = pool_alloc (pool, sizeof *g);
674   g->type = POOL_GIZMO_FILE;
675   g->p.file = file;
676   add_gizmo (pool, g);
677 }
678
679 /* Detaches FILE from POOL. */
680 void
681 pool_detach_file (struct pool *pool, FILE *file)
682 {
683   struct pool_gizmo *g;
684
685   for (g = pool->gizmos; g; g = g->next)
686     if (g->type == POOL_GIZMO_FILE && g->p.file == file)
687       {
688         delete_gizmo (pool, g);
689         return;
690       }
691 }
692 \f
693 /* Registers FREE to be called with argument P.
694    P should be unique among those registered in POOL so that it can be
695    uniquely identified by pool_unregister().
696    If not unregistered, FREE will be called with argument P when POOL
697    is destroyed. */
698 void
699 pool_register (struct pool *pool, void (*free) (void *), void *p)
700 {
701   assert (pool && free && p);
702
703   {
704     struct pool_gizmo *g = pool_alloc (pool, sizeof *g);
705     g->type = POOL_GIZMO_REGISTERED;
706     g->p.registered.free = free;
707     g->p.registered.p = p;
708     add_gizmo (pool, g);
709   }
710 }
711
712 /* Unregisters previously registered P from POOL.
713    Returns nonzero only if P was found to be registered in POOL. */
714 int
715 pool_unregister (struct pool *pool, void *p)
716 {
717   assert (pool && p);
718   
719   {
720     struct pool_gizmo *g;
721
722     for (g = pool->gizmos; g; g = g->next)
723       if (g->type == POOL_GIZMO_REGISTERED && g->p.registered.p == p)
724         {
725           delete_gizmo (pool, g);
726           return 1;
727         }
728   }
729   
730   return 0;
731 }
732 \f
733 /* Partial freeing. */
734
735 /* Notes the state of POOL into MARK so that it may be restored
736    by a call to pool_release(). */
737 void
738 pool_mark (struct pool *pool, struct pool_mark *mark)
739 {
740   assert (pool && mark);
741
742   mark->block = pool->blocks;
743   mark->ofs = pool->blocks->ofs;
744
745   mark->serial = serial;
746 }
747
748 /* Restores to POOL the state recorded in MARK.
749    Emptied blocks are not given back with free() but kept for
750    later allocations.  To get that behavior, use a subpool
751    instead. */ 
752 void
753 pool_release (struct pool *pool, const struct pool_mark *mark)
754 {
755   assert (pool && mark);
756   
757   {
758     struct pool_gizmo *cur, *next;
759
760     for (cur = pool->gizmos; cur && cur->serial >= mark->serial; cur = next)
761       {
762         next = cur->next;
763         free_gizmo (cur);
764       }
765
766     if (cur != NULL)
767       {
768         cur->prev = NULL;
769         pool->gizmos = cur;
770       }
771     else
772       pool->gizmos = NULL;
773   }
774   
775   {
776     struct pool_block *cur;
777
778     for (cur = pool->blocks; cur != mark->block; cur = cur->next) 
779       {
780         cur->ofs = POOL_BLOCK_SIZE;
781         if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool) 
782           {
783             cur->ofs += POOL_SIZE;
784             if (pool->parent != NULL)
785               cur->ofs += POOL_GIZMO_SIZE; 
786           }
787       }
788     pool->blocks = mark->block;
789     pool->blocks->ofs = mark->ofs;
790   }
791 }
792 \f
793 /* Private functions. */
794
795 /* Adds GIZMO at the beginning of POOL's gizmo list. */
796 static void
797 add_gizmo (struct pool *pool, struct pool_gizmo *gizmo)
798 {
799   assert (pool && gizmo);
800
801   gizmo->pool = pool;
802   gizmo->next = pool->gizmos;
803   gizmo->prev = NULL;
804   if (pool->gizmos)
805     pool->gizmos->prev = gizmo;
806   pool->gizmos = gizmo;
807
808   gizmo->serial = serial++;
809
810   check_gizmo (pool, gizmo);
811 }
812  
813 /* Removes GIZMO from POOL's gizmo list. */
814 static void
815 delete_gizmo (struct pool *pool, struct pool_gizmo *gizmo)
816 {
817   assert (pool && gizmo);
818
819   check_gizmo (pool, gizmo);
820
821   if (gizmo->prev)
822     gizmo->prev->next = gizmo->next;
823   else
824     pool->gizmos = gizmo->next;
825   if (gizmo->next)
826     gizmo->next->prev = gizmo->prev;
827 }
828
829 /* Frees any of GIZMO's internal state.
830    GIZMO's data must not be referenced after calling this function. */
831 static void
832 free_gizmo (struct pool_gizmo *gizmo)
833 {
834   assert (gizmo != NULL);
835
836   switch (gizmo->type)
837     {
838     case POOL_GIZMO_MALLOC:
839       free (gizmo);
840       break;
841     case POOL_GIZMO_FILE:
842       fclose (gizmo->p.file);   /* Ignore errors. */
843       break;
844     case POOL_GIZMO_SUBPOOL:
845       gizmo->p.subpool->parent = NULL;
846       pool_destroy (gizmo->p.subpool);
847       break;
848     case POOL_GIZMO_REGISTERED:
849       gizmo->p.registered.free (gizmo->p.registered.p);
850       break;
851     default:
852       assert (0);
853     }
854 }
855
856 /* Free all the gizmos in POOL. */
857 static void
858 free_all_gizmos (struct pool *pool) 
859 {
860   struct pool_gizmo *cur, *next;
861
862   for (cur = pool->gizmos; cur; cur = next)
863     {
864       next = cur->next;
865       free_gizmo (cur);
866     }
867   pool->gizmos = NULL;
868 }
869
870 static void
871 check_gizmo (struct pool *p, struct pool_gizmo *g) 
872 {
873   assert (g->pool == p);
874   assert (g->next == NULL || g->next->prev == g);
875   assert ((g->prev != NULL && g->prev->next == g)
876           || (g->prev == NULL && p->gizmos == g));
877
878 }