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