xalloc: Add x2realloc function, from gnulib.

* gnulib-local/lib/xalloc.h (x2realloc): New declaration, from
gnulib/lib/xalloc.h.
* gnulib-local/lib/xmalloc.c (x2nrealloc): New function, from
gnulib/lib/xalloc.h.
(x2realloc): New function, from gnulib/lib/xmalloc.c.
* gnulib-local/modules/xalloc (configure.ac): Require AC_C_INLINE.
This commit is contained in:
Bruno Haible
2019-08-12 03:31:49 +02:00
parent 9a4495f84f
commit 8e280e2efd
3 changed files with 120 additions and 0 deletions
+16
View File
@@ -58,6 +58,22 @@ template <typename T>
extern "C" {
#endif
/* If P is null, allocate a block of at least *PN bytes; otherwise,
reallocate P so that it contains more than *PN bytes. *PN must be
nonzero unless P is null. Set *PN to the new block's size, and
return the pointer to the new block. *PN is never set to zero, and
the returned pointer is never null. */
extern void *x2realloc (void *ptr, size_t *pn);
#ifdef __cplusplus
}
template <typename T>
inline T * x2realloc (T * ptr, size_t *pn)
{
return (T *) x2realloc ((void *) ptr, pn);
}
extern "C" {
#endif
/* This function is always triggered when memory is exhausted. It is
in charge of honoring the three previous items. This is the
function to call when one wants the program to die because of a
+103
View File
@@ -127,3 +127,106 @@ xrealloc (void *p, size_t n)
p = fixup_null_alloc (n);
return p;
}
/* If P is null, allocate a block of at least *PN such objects;
otherwise, reallocate P so that it contains more than *PN objects
each of S bytes. S must be nonzero. Set *PN to the new number of
objects, and return the pointer to the new block. *PN is never set
to zero, and the returned pointer is never null.
Repeated reallocations are guaranteed to make progress, either by
allocating an initial block with a nonzero size, or by allocating a
larger block.
In the following implementation, nonzero sizes are increased by a
factor of approximately 1.5 so that repeated reallocations have
O(N) overall cost rather than O(N**2) cost, but the
specification for this function does not guarantee that rate.
Here is an example of use:
int *p = NULL;
size_t used = 0;
size_t allocated = 0;
void
append_int (int value)
{
if (used == allocated)
p = x2nrealloc (p, &allocated, sizeof *p);
p[used++] = value;
}
This causes x2nrealloc to allocate a block of some nonzero size the
first time it is called.
To have finer-grained control over the initial size, set *PN to a
nonzero value before calling this function with P == NULL. For
example:
int *p = NULL;
size_t used = 0;
size_t allocated = 0;
size_t allocated1 = 1000;
void
append_int (int value)
{
if (used == allocated)
{
p = x2nrealloc (p, &allocated1, sizeof *p);
allocated = allocated1;
}
p[used++] = value;
}
*/
static inline void *
x2nrealloc (void *p, size_t *pn, size_t s)
{
size_t n = *pn;
if (! p)
{
if (! n)
{
/* The approximate size to use for initial small allocation
requests, when the invoking code specifies an old size of
zero. This is the largest "small" request for the GNU C
library malloc. */
enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
n = DEFAULT_MXFAST / s;
n += !n;
}
if (xalloc_oversized (n, s))
xalloc_die ();
}
else
{
/* Set N = floor (1.5 * N) + 1 so that progress is made even if N == 0.
Check for overflow, so that N * S stays in both ptrdiff_t and
size_t range. The check may be slightly conservative, but an
exact check isn't worth the trouble. */
if ((PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX) / 3 * 2 / s
<= n)
xalloc_die ();
n += n / 2 + 1;
}
*pn = n;
return xrealloc (p, n * s);
}
/* If P is null, allocate a block of at least *PN bytes; otherwise,
reallocate P so that it contains more than *PN bytes. *PN must be
nonzero unless P is null. Set *PN to the new block's size, and
return the pointer to the new block. *PN is never set to zero, and
the returned pointer is never null. */
void *
x2realloc (void *p, size_t *pn)
{
return x2nrealloc (p, pn, 1);
}
+1
View File
@@ -13,6 +13,7 @@ stdlib
xalloc-oversized
configure.ac:
AC_REQUIRE([AC_C_INLINE])
Makefile.am:
lib_SOURCES += xalloc.h xmalloc.c xstrdup.c