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