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