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