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