summaryrefslogtreecommitdiff
path: root/lib/xalloc.h
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2006-11-06 21:24:35 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2006-11-06 21:24:35 +0000
commitac2a728a11acdae91051359487c52acc9d180a8e (patch)
tree609637805447a082b6621a4a4332d88c5888c640 /lib/xalloc.h
parent0c0219f84c3c29237187f0640248eef23c815900 (diff)
downloadgnulib-ac2a728a11acdae91051359487c52acc9d180a8e.tar.gz
* lib/xalloc.h (xnmalloc, xnrealloc, x2nrealloc): Now static
inline functions that are identical with the old xnmalloc_inline, xnrealloc_inline, x2nrealloc_inline of lib/xmalloc.c. This is so that we can avoid some unnecessary integer multiplications and divisions in the common case where the element size is known at compile time. (XNMALLOC) [HAVE_INLINE]: Remove special case, which is no longer needed. (xnboundedmalloc): Remove. (XMALLOC, XNMALLOC, XZALLOC, XCALLOC): Use lower-case letters for arguments, for consistency with rest of this header. (xcharalloc): Rewrite using XNMALLOC. * lib/xmalloc.c (xnmalloc_inline, xnmalloc, xnrealloc_inline): (xnrealloc, x2nrealloc_inline, x2nrealloc): Remove. The *_inline versions have been moved to lib/xalloc.h and renamed to be the non-*_inline versions. (xmalloc, xrealloc): Implement without reference to the xnmalloc and xnrealloc functions, since those functions are now inline and now call us. (x2realloc): Invoke x2realloc, not x2realloc_inline, to accommodate renaming described above.
Diffstat (limited to 'lib/xalloc.h')
-rw-r--r--lib/xalloc.h160
1 files changed, 121 insertions, 39 deletions
diff --git a/lib/xalloc.h b/lib/xalloc.h
index 6881ea678d..459e37a0ed 100644
--- a/lib/xalloc.h
+++ b/lib/xalloc.h
@@ -1,7 +1,7 @@
/* xalloc.h -- malloc with out-of-memory checking
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2003, 2004, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -46,13 +46,10 @@ extern "C" {
extern void xalloc_die (void) ATTRIBUTE_NORETURN;
void *xmalloc (size_t s);
-void *xnmalloc (size_t n, size_t s);
void *xzalloc (size_t s);
void *xcalloc (size_t n, size_t s);
void *xrealloc (void *p, size_t s);
-void *xnrealloc (void *p, size_t n, size_t s);
void *x2realloc (void *p, size_t *pn);
-void *x2nrealloc (void *p, size_t *pn, size_t s);
void *xmemdup (void const *p, size_t s);
char *xstrdup (char const *str);
@@ -71,57 +68,142 @@ char *xstrdup (char const *str);
# define xalloc_oversized(n, s) \
((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
-/* In the following macros, T must be an elementary or structure/union or
- typedef'ed type, or a pointer to such a type. To apply one of the
- following macros to a function pointer or array type, you need to typedef
- it first and use the typedef name. */
+/* Allocate an array of N objects, each with S bytes of memory,
+ dynamically, with error checking. S must be nonzero. */
-/* Allocate an object of type T dynamically, with error checking. */
-/* extern T *XMALLOC (typename T); */
-#define XMALLOC(T) \
- ((T *) xmalloc (sizeof (T)))
-
-/* Allocate memory for NMEMB elements of type T, with error checking. */
-/* extern T *XNMALLOC (size_t nmemb, typename T); */
-#if HAVE_INLINE
-/* xnmalloc performs a division and multiplication by sizeof (T). Arrange to
- perform the division at compile-time and the multiplication with a factor
- known at compile-time. */
-# define XNMALLOC(N,T) \
- ((T *) (sizeof (T) == 1 \
- ? xmalloc (N) \
- : xnboundedmalloc(N, (size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / sizeof (T), sizeof (T))))
static inline void *
-xnboundedmalloc (size_t n, size_t bound, size_t s)
+xnmalloc (size_t n, size_t s)
{
- if (n > bound)
+ if (xalloc_oversized (n, s))
xalloc_die ();
return xmalloc (n * s);
}
-#else
-# define XNMALLOC(N,T) \
- ((T *) (sizeof (T) == 1 ? xmalloc (N) : xnmalloc (N, sizeof (T))))
-#endif
+
+/* Change the size of an allocated block of memory P to an array of N
+ objects each of S bytes, with error checking. S must be nonzero. */
+
+static inline void *
+xnrealloc (void *p, size_t n, size_t s)
+{
+ if (xalloc_oversized (n, s))
+ xalloc_die ();
+ return xrealloc (p, n * s);
+}
+
+/* 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. *PN must be nonzero unless P is null, and 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 doubled so that
+ repeated reallocations have O(N log N) overall cost rather than
+ O(N**2) cost, but the specification for this function does not
+ guarantee that sizes are doubled.
+
+ 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. 64 bytes is the largest "small" request for the
+ GNU C library malloc. */
+ enum { DEFAULT_MXFAST = 64 };
+
+ n = DEFAULT_MXFAST / s;
+ n += !n;
+ }
+ }
+ else
+ {
+ if (((size_t) -1) / 2 / s < n)
+ xalloc_die ();
+ n *= 2;
+ }
+
+ *pn = n;
+ return xrealloc (p, n * s);
+}
+
+/* In the following macros, T must be an elementary or structure/union or
+ typedef'ed type, or a pointer to such a type. To apply one of the
+ following macros to a function pointer or array type, you need to typedef
+ it first and use the typedef name. */
+
+/* Allocate an object of type T dynamically, with error checking. */
+/* extern t *XMALLOC (typename t); */
+#define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
+
+/* Allocate memory for N elements of type T, with error checking. */
+/* extern t *XNMALLOC (size_t n, typename t); */
+#define XNMALLOC(n, t) ((t *) xnmalloc (n, sizeof (t)))
/* Allocate an object of type T dynamically, with error checking,
and zero it. */
-/* extern T *XZALLOC (typename T); */
-#define XZALLOC(T) \
- ((T *) xzalloc (sizeof (T)))
+/* extern t *XZALLOC (typename t); */
+#define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
-/* Allocate memory for NMEMB elements of type T, with error checking,
+/* Allocate memory for N elements of type T, with error checking,
and zero it. */
-/* extern T *XCALLOC (size_t nmemb, typename T); */
-#define XCALLOC(N,T) \
- ((T *) xcalloc (N, sizeof (T)))
+/* extern t *XCALLOC (size_t n, typename t); */
+#define XCALLOC(n, t) ((t *) xcalloc (n, sizeof (t)))
/* Return a pointer to a new buffer of N bytes. This is like xmalloc,
- except it returns char *.
- xcharalloc (N) is equivalent to XNMALLOC (N, char). */
+ except it returns char *. */
static inline char *
xcharalloc (size_t n)
{
- return (char *) xmalloc (n);
+ return XNMALLOC (n, char);
}
# ifdef __cplusplus