Remove "Written by Ben Pfaff <blp@gnu.org>" lines everywhere.
[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 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
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 /* Changes the allocation size of the specified memory block P managed
476    by POOL to AMT bytes and returns a pointer to the beginning of the
477    block.
478    If POOL is a null pointer, then the block is reallocated in the
479    usual way with realloc(). */
480 void *
481 pool_realloc (struct pool *pool, void *p, size_t amt)
482 {
483   if (pool != NULL)
484     {
485       if (p != NULL)
486         {
487           if (amt != 0)
488             {
489               struct pool_gizmo *g = (void *) (((char *) p) - POOL_GIZMO_SIZE);
490               check_gizmo (pool, g);
491
492               g = xrealloc (g, amt + POOL_GIZMO_SIZE);
493               if (g->next)
494                 g->next->prev = g;
495               if (g->prev)
496                 g->prev->next = g;
497               else
498                 pool->gizmos = g;
499               check_gizmo (pool, g);
500
501               return ((char *) g) + POOL_GIZMO_SIZE;
502             }
503           else
504             {
505               pool_free (pool, p);
506               return NULL;
507             }
508         }
509       else
510         return pool_malloc (pool, amt);
511     }
512   else
513     return xrealloc (p, amt);
514 }
515
516 /* Changes the allocation size of the specified memory block P
517    managed by POOL to N * S bytes and returns a pointer to the
518    beginning of the block.
519    N must be nonnegative, S must be positive.
520    If POOL is a null pointer, then the block is reallocated in
521    the usual way with xrealloc().
522    Terminates the program if the memory cannot be obtained,
523    including the case where N * S overflows the range of size_t. */
524 void *
525 pool_nrealloc (struct pool *pool, void *p, size_t n, size_t s)
526 {
527   if (xalloc_oversized (n, s))
528     xalloc_die ();
529   return pool_realloc (pool, p, n * s);
530 }
531
532 /* If P is null, allocate a block of at least *PN such objects;
533    otherwise, reallocate P so that it contains more than *PN
534    objects each of S bytes.  *PN must be nonzero unless P is
535    null, and S must be nonzero.  Set *PN to the new number of
536    objects, and return the pointer to the new block.  *PN is
537    never set to zero, and the returned pointer is never null.
538
539    The block returned is managed by POOL.  If POOL is a null
540    pointer, then the block is reallocated in the usual way with
541    x2nrealloc().
542
543    Terminates the program if the memory cannot be obtained,
544    including the case where the memory required overflows the
545    range of size_t.
546
547    Repeated reallocations are guaranteed to make progress, either by
548    allocating an initial block with a nonzero size, or by allocating a
549    larger block.
550
551    In the following implementation, nonzero sizes are doubled so that
552    repeated reallocations have O(N log N) overall cost rather than
553    O(N**2) cost, but the specification for this function does not
554    guarantee that sizes are doubled.
555
556    Here is an example of use:
557
558      int *p = NULL;
559      struct pool *pool;
560      size_t used = 0;
561      size_t allocated = 0;
562
563      void
564      append_int (int value)
565        {
566          if (used == allocated)
567            p = pool_2nrealloc (pool, p, &allocated, sizeof *p);
568          p[used++] = value;
569        }
570
571    This causes x2nrealloc to allocate a block of some nonzero size the
572    first time it is called.
573
574    To have finer-grained control over the initial size, set *PN to a
575    nonzero value before calling this function with P == NULL.  For
576    example:
577
578      int *p = NULL;
579      struct pool *pool;
580      size_t used = 0;
581      size_t allocated = 0;
582      size_t allocated1 = 1000;
583
584      void
585      append_int (int value)
586        {
587          if (used == allocated)
588            {
589              p = pool_2nrealloc (pool, p, &allocated1, sizeof *p);
590              allocated = allocated1;
591            }
592          p[used++] = value;
593        }
594
595    This function implementation is from gnulib. */
596 void *
597 pool_2nrealloc (struct pool *pool, void *p, size_t *pn, size_t s)
598 {
599   size_t n = *pn;
600
601   if (p == NULL)
602     {
603       if (n == 0)
604         {
605           /* The approximate size to use for initial small allocation
606              requests, when the invoking code specifies an old size of
607              zero.  64 bytes is the largest "small" request for the
608              GNU C library malloc.  */
609           enum { DEFAULT_MXFAST = 64 };
610
611           n = DEFAULT_MXFAST / s;
612           n += !n;
613         }
614     }
615   else
616     {
617       if (SIZE_MAX / 2 / s < n)
618         xalloc_die ();
619       n *= 2;
620     }
621
622   *pn = n;
623   return pool_realloc (pool, p, n * s);
624 }
625
626 /* Frees block P managed by POOL.
627    If POOL is a null pointer, then the block is freed as usual with
628    free(). */
629 void
630 pool_free (struct pool *pool, void *p)
631 {
632   if (pool != NULL && p != NULL)
633     {
634       struct pool_gizmo *g = (void *) (((char *) p) - POOL_GIZMO_SIZE);
635       check_gizmo (pool, g);
636       delete_gizmo (pool, g);
637       free (g);
638     }
639   else
640     free (p);
641 }
642 \f
643 /* Gizmo allocations. */
644
645 /* Creates and returns a pool as a subpool of POOL.
646    The subpool will be destroyed automatically when POOL is destroyed.
647    It may also be destroyed explicitly in advance. */
648 struct pool *
649 pool_create_subpool (struct pool *pool)
650 {
651   struct pool *subpool;
652   struct pool_gizmo *g;
653
654   assert (pool != NULL);
655   subpool = pool_create ();
656   subpool->parent = pool;
657
658   g = (void *) (((char *) subpool->blocks) + subpool->blocks->ofs);
659   subpool->blocks->ofs += POOL_GIZMO_SIZE;
660   
661   g->type = POOL_GIZMO_SUBPOOL;
662   g->p.subpool = subpool;
663
664   add_gizmo (pool, g);
665
666   return subpool;
667 }
668
669 /* Makes SUBPOOL a subpool of POOL.
670    SUBPOOL must not already have a parent pool.
671    The subpool will be destroyed automatically when POOL is destroyed.
672    It may also be destroyed explicitly in advance. */
673 void
674 pool_add_subpool (struct pool *pool, struct pool *subpool) 
675 {
676   struct pool_gizmo *g;
677
678   assert (pool != NULL);
679   assert (subpool != NULL);
680   assert (subpool->parent == NULL);
681   
682   g = pool_alloc (subpool, sizeof *g);
683   g->type = POOL_GIZMO_SUBPOOL;
684   g->p.subpool = subpool;
685   add_gizmo (pool, g);
686
687   subpool->parent = pool;
688 }
689
690 /* Opens file FILE_NAME with mode MODE and returns a handle to it
691    if successful or a null pointer if not.
692    The file will be closed automatically when POOL is destroyed, or it
693    may be closed explicitly in advance using pool_fclose(), or
694    detached from the pool with pool_detach_file(). */
695 FILE *
696 pool_fopen (struct pool *pool, const char *file_name, const char *mode)
697 {
698   FILE *f;
699
700   assert (pool && file_name && mode);
701   f = fopen (file_name, mode);
702   if (f != NULL)
703     pool_attach_file (pool, f);
704
705   return f;
706 }
707
708 /* Closes file FILE managed by POOL.
709    Returns 0 if successful, EOF if an I/O error occurred. */
710 int
711 pool_fclose (struct pool *pool, FILE *file)
712 {
713   assert (pool && file);
714   pool_detach_file (pool, file);
715   return fclose (file);
716 }
717
718 /* Creates a temporary file with tmpfile() 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_tmpfile (struct pool *pool) 
725 {
726   FILE *file = tmpfile ();
727   if (file != NULL)
728     pool_attach_file (pool, file);
729   return file;
730 }
731
732 /* Attaches FILE to POOL.
733    The file will be closed automatically when POOL is destroyed, or it
734    may be closed explicitly in advance using pool_fclose(), or
735    detached from the pool with pool_detach_file(). */
736 void
737 pool_attach_file (struct pool *pool, FILE *file)
738 {
739   struct pool_gizmo *g = pool_alloc (pool, sizeof *g);
740   g->type = POOL_GIZMO_FILE;
741   g->p.file = file;
742   add_gizmo (pool, g);
743 }
744
745 /* Detaches FILE from POOL. */
746 void
747 pool_detach_file (struct pool *pool, FILE *file)
748 {
749   struct pool_gizmo *g;
750
751   for (g = pool->gizmos; g; g = g->next)
752     if (g->type == POOL_GIZMO_FILE && g->p.file == file)
753       {
754         delete_gizmo (pool, g);
755         return;
756       }
757 }
758 \f
759 /* Registers FREE to be called with argument P.
760    P should be unique among those registered in POOL so that it can be
761    uniquely identified by pool_unregister().
762    If not unregistered, FREE will be called with argument P when POOL
763    is destroyed. */
764 void
765 pool_register (struct pool *pool, void (*free) (void *), void *p)
766 {
767   assert (pool && free && p);
768
769   {
770     struct pool_gizmo *g = pool_alloc (pool, sizeof *g);
771     g->type = POOL_GIZMO_REGISTERED;
772     g->p.registered.free = free;
773     g->p.registered.p = p;
774     add_gizmo (pool, g);
775   }
776 }
777
778 /* Unregisters previously registered P from POOL.
779    Returns true only if P was found to be registered in POOL. */
780 bool
781 pool_unregister (struct pool *pool, void *p)
782 {
783   assert (pool && p);
784   
785   {
786     struct pool_gizmo *g;
787
788     for (g = pool->gizmos; g; g = g->next)
789       if (g->type == POOL_GIZMO_REGISTERED && g->p.registered.p == p)
790         {
791           delete_gizmo (pool, g);
792           return true;
793         }
794   }
795   
796   return false;
797 }
798 \f
799 /* Partial freeing. */
800
801 /* Notes the state of POOL into MARK so that it may be restored
802    by a call to pool_release(). */
803 void
804 pool_mark (struct pool *pool, struct pool_mark *mark)
805 {
806   assert (pool && mark);
807
808   mark->block = pool->blocks;
809   mark->ofs = pool->blocks->ofs;
810
811   mark->serial = serial;
812 }
813
814 /* Restores to POOL the state recorded in MARK.
815    Emptied blocks are not given back with free() but kept for
816    later allocations.  To get that behavior, use a subpool
817    instead. */ 
818 void
819 pool_release (struct pool *pool, const struct pool_mark *mark)
820 {
821   assert (pool && mark);
822   
823   {
824     struct pool_gizmo *cur, *next;
825
826     for (cur = pool->gizmos; cur && cur->serial >= mark->serial; cur = next)
827       {
828         next = cur->next;
829         free_gizmo (cur);
830       }
831
832     if (cur != NULL)
833       {
834         cur->prev = NULL;
835         pool->gizmos = cur;
836       }
837     else
838       pool->gizmos = NULL;
839   }
840   
841   {
842     struct pool_block *cur;
843
844     for (cur = pool->blocks; cur != mark->block; cur = cur->next) 
845       {
846         cur->ofs = POOL_BLOCK_SIZE;
847         if ((char *) cur + POOL_BLOCK_SIZE == (char *) pool) 
848           {
849             cur->ofs += POOL_SIZE;
850             if (pool->parent != NULL)
851               cur->ofs += POOL_GIZMO_SIZE; 
852           }
853       }
854     pool->blocks = mark->block;
855     pool->blocks->ofs = mark->ofs;
856   }
857 }
858 \f
859 /* Private functions. */
860
861 /* Adds GIZMO at the beginning of POOL's gizmo list. */
862 static void
863 add_gizmo (struct pool *pool, struct pool_gizmo *gizmo)
864 {
865   assert (pool && gizmo);
866
867   gizmo->pool = pool;
868   gizmo->next = pool->gizmos;
869   gizmo->prev = NULL;
870   if (pool->gizmos)
871     pool->gizmos->prev = gizmo;
872   pool->gizmos = gizmo;
873
874   gizmo->serial = serial++;
875
876   check_gizmo (pool, gizmo);
877 }
878  
879 /* Removes GIZMO from POOL's gizmo list. */
880 static void
881 delete_gizmo (struct pool *pool, struct pool_gizmo *gizmo)
882 {
883   assert (pool && gizmo);
884
885   check_gizmo (pool, gizmo);
886
887   if (gizmo->prev)
888     gizmo->prev->next = gizmo->next;
889   else
890     pool->gizmos = gizmo->next;
891   if (gizmo->next)
892     gizmo->next->prev = gizmo->prev;
893 }
894
895 /* Frees any of GIZMO's internal state.
896    GIZMO's data must not be referenced after calling this function. */
897 static void
898 free_gizmo (struct pool_gizmo *gizmo)
899 {
900   assert (gizmo != NULL);
901
902   switch (gizmo->type)
903     {
904     case POOL_GIZMO_MALLOC:
905       free (gizmo);
906       break;
907     case POOL_GIZMO_FILE:
908       fclose (gizmo->p.file);   /* Ignore errors. */
909       break;
910     case POOL_GIZMO_SUBPOOL:
911       gizmo->p.subpool->parent = NULL;
912       pool_destroy (gizmo->p.subpool);
913       break;
914     case POOL_GIZMO_REGISTERED:
915       gizmo->p.registered.free (gizmo->p.registered.p);
916       break;
917     default:
918       NOT_REACHED ();
919     }
920 }
921
922 /* Free all the gizmos in POOL. */
923 static void
924 free_all_gizmos (struct pool *pool) 
925 {
926   struct pool_gizmo *cur, *next;
927
928   for (cur = pool->gizmos; cur; cur = next)
929     {
930       next = cur->next;
931       free_gizmo (cur);
932     }
933   pool->gizmos = NULL;
934 }
935
936 static void
937 check_gizmo (struct pool *p, struct pool_gizmo *g) 
938 {
939   assert (g->pool == p);
940   assert (g->next == NULL || g->next->prev == g);
941   assert ((g->prev != NULL && g->prev->next == g)
942           || (g->prev == NULL && p->gizmos == g));
943
944 }