19 |
|
|
20 |
#include <config.h> |
#include <config.h> |
21 |
#include "pool.h" |
#include "pool.h" |
|
#include "command.h" |
|
|
#include "error.h" |
|
22 |
#include <stdlib.h> |
#include <stdlib.h> |
23 |
#include "alloc.h" |
#include "alloc.h" |
24 |
|
#include "command.h" |
25 |
|
#include "error.h" |
26 |
|
#include "size_max.h" |
27 |
#include "str.h" |
#include "str.h" |
28 |
|
|
29 |
/* Fast, low-overhead memory block suballocator. */ |
/* Fast, low-overhead memory block suballocator. */ |
348 |
/* Allocates AMT bytes using malloc(), to be managed by POOL, and |
/* Allocates AMT bytes using malloc(), to be managed by POOL, and |
349 |
returns a pointer to the beginning of the block. |
returns a pointer to the beginning of the block. |
350 |
If POOL is a null pointer, then allocates a normal memory block |
If POOL is a null pointer, then allocates a normal memory block |
351 |
with malloc(). */ |
with xmalloc(). */ |
352 |
void * |
void * |
353 |
pool_malloc (struct pool *pool, size_t amt) |
pool_malloc (struct pool *pool, size_t amt) |
354 |
{ |
{ |
441 |
return pool_realloc (pool, p, n * s); |
return pool_realloc (pool, p, n * s); |
442 |
} |
} |
443 |
|
|
444 |
|
/* If P is null, allocate a block of at least *PN such objects; |
445 |
|
otherwise, reallocate P so that it contains more than *PN |
446 |
|
objects each of S bytes. *PN must be nonzero unless P is |
447 |
|
null, and S must be nonzero. Set *PN to the new number of |
448 |
|
objects, and return the pointer to the new block. *PN is |
449 |
|
never set to zero, and the returned pointer is never null. |
450 |
|
|
451 |
|
The block returned is managed by POOL. If POOL is a null |
452 |
|
pointer, then the block is reallocated in the usual way with |
453 |
|
x2nrealloc(). |
454 |
|
|
455 |
|
Terminates the program if the memory cannot be obtained, |
456 |
|
including the case where the memory required overflows the |
457 |
|
range of size_t. |
458 |
|
|
459 |
|
Repeated reallocations are guaranteed to make progress, either by |
460 |
|
allocating an initial block with a nonzero size, or by allocating a |
461 |
|
larger block. |
462 |
|
|
463 |
|
In the following implementation, nonzero sizes are doubled so that |
464 |
|
repeated reallocations have O(N log N) overall cost rather than |
465 |
|
O(N**2) cost, but the specification for this function does not |
466 |
|
guarantee that sizes are doubled. |
467 |
|
|
468 |
|
Here is an example of use: |
469 |
|
|
470 |
|
int *p = NULL; |
471 |
|
struct pool *pool; |
472 |
|
size_t used = 0; |
473 |
|
size_t allocated = 0; |
474 |
|
|
475 |
|
void |
476 |
|
append_int (int value) |
477 |
|
{ |
478 |
|
if (used == allocated) |
479 |
|
p = pool_2nrealloc (pool, p, &allocated, sizeof *p); |
480 |
|
p[used++] = value; |
481 |
|
} |
482 |
|
|
483 |
|
This causes x2nrealloc to allocate a block of some nonzero size the |
484 |
|
first time it is called. |
485 |
|
|
486 |
|
To have finer-grained control over the initial size, set *PN to a |
487 |
|
nonzero value before calling this function with P == NULL. For |
488 |
|
example: |
489 |
|
|
490 |
|
int *p = NULL; |
491 |
|
struct pool *pool; |
492 |
|
size_t used = 0; |
493 |
|
size_t allocated = 0; |
494 |
|
size_t allocated1 = 1000; |
495 |
|
|
496 |
|
void |
497 |
|
append_int (int value) |
498 |
|
{ |
499 |
|
if (used == allocated) |
500 |
|
{ |
501 |
|
p = pool_2nrealloc (pool, p, &allocated1, sizeof *p); |
502 |
|
allocated = allocated1; |
503 |
|
} |
504 |
|
p[used++] = value; |
505 |
|
} |
506 |
|
|
507 |
|
This function implementation is from gnulib. */ |
508 |
|
void * |
509 |
|
pool_2nrealloc (struct pool *pool, void *p, size_t *pn, size_t s) |
510 |
|
{ |
511 |
|
size_t n = *pn; |
512 |
|
|
513 |
|
if (p == NULL) |
514 |
|
{ |
515 |
|
if (n == 0) |
516 |
|
{ |
517 |
|
/* The approximate size to use for initial small allocation |
518 |
|
requests, when the invoking code specifies an old size of |
519 |
|
zero. 64 bytes is the largest "small" request for the |
520 |
|
GNU C library malloc. */ |
521 |
|
enum { DEFAULT_MXFAST = 64 }; |
522 |
|
|
523 |
|
n = DEFAULT_MXFAST / s; |
524 |
|
n += !n; |
525 |
|
} |
526 |
|
} |
527 |
|
else |
528 |
|
{ |
529 |
|
if (SIZE_MAX / 2 / s < n) |
530 |
|
xalloc_die (); |
531 |
|
n *= 2; |
532 |
|
} |
533 |
|
|
534 |
|
*pn = n; |
535 |
|
return pool_realloc (pool, p, n * s); |
536 |
|
} |
537 |
|
|
538 |
/* Frees block P managed by POOL. |
/* Frees block P managed by POOL. |
539 |
If POOL is a null pointer, then the block is freed as usual with |
If POOL is a null pointer, then the block is freed as usual with |
540 |
free(). */ |
free(). */ |