chiark / gitweb /
Merge branch 'work'
[mLib] / sub.c
diff --git a/sub.c b/sub.c
index 45dcac46a5606af1aee313275c35704b39ad5315..06570b609b0e629e68198faf04b6aaeefa99ff75 100644 (file)
--- a/sub.c
+++ b/sub.c
@@ -1,13 +1,13 @@
 /* -*-c-*-
  *
- * $Id: sub.c,v 1.6 2000/06/17 10:35:51 mdw Exp $
+ * $Id: sub.c,v 1.9 2004/04/08 01:36:13 mdw Exp $
  *
  * Allocation of known-size blocks
  *
  * (c) 1998 Straylight/Edgeware
  */
 
-/*----- Licensing notice --------------------------------------------------* 
+/*----- Licensing notice --------------------------------------------------*
  *
  * This file is part of the mLib utilities library.
  *
  * it under the terms of the GNU Library General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
- * 
+ *
  * mLib is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Library General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Library General Public
  * License along with mLib; if not, write to the Free
  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  * MA 02111-1307, USA.
  */
 
-/*----- Revision history --------------------------------------------------*
- *
- * $Log: sub.c,v $
- * Revision 1.6  2000/06/17 10:35:51  mdw
- * Major overhaul for arena support.
- *
- * Revision 1.5  1999/05/19 20:27:11  mdw
- * Change naming to match newer mLib conventions.
- *
- * Revision 1.4  1999/05/13 22:48:55  mdw
- * Change `-ise' to `-ize' throughout.
- *
- * Revision 1.3  1999/05/06 19:51:35  mdw
- * Reformatted the LGPL notice a little bit.
- *
- * Revision 1.2  1999/05/05 18:50:31  mdw
- * Change licensing conditions to LGPL.
- *
- * Revision 1.1.1.1  1998/06/17 23:44:42  mdw
- * Initial version of mLib
- *
- */
-
 /*----- The big idea ------------------------------------------------------*
  *
  * This file provides an extra layer over @malloc@.  It provides fast
@@ -83,6 +60,7 @@
 
 /* --- ANSI headers --- */
 
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "exc.h"
 #include "sub.h"
 
+/*----- Configuration tweaks ----------------------------------------------*/
+
+/* #define SUBARENA_TRIVIAL */
+
 /*----- Static variables --------------------------------------------------*/
 
 static size_t sizes[SUB_BINS];
@@ -101,6 +83,16 @@ static size_t sizes[SUB_BINS];
 
 subarena sub_global;
 
+#ifdef SUBARENA_TRIVIAL
+
+typedef struct sub_link {
+  struct sub_link *next;
+  void *p;
+  size_t sz;
+} sub_link;
+
+#endif
+
 /*----- Main code ---------------------------------------------------------*/
 
 /* --- @subarena_create@ --- *
@@ -116,11 +108,15 @@ subarena sub_global;
 
 void subarena_create(subarena *s, arena *a)
 {
+#ifdef SUBARENA_TRIVIAL
+  s->bin[0] = 0;
+#else
   size_t i;
   if (!sizes[1])
     sub_init();
   for (i = 0; i < SUB_BINS; i++)
     s->bin[i] = 0;
+#endif
   s->a = a;
 }
 
@@ -136,6 +132,19 @@ void subarena_create(subarena *s, arena *a)
 
 void subarena_destroy(subarena *s)
 {
+#ifdef SUBARENA_TRIVIAL
+
+  sub_link *l, *ll;
+
+  for (l = s->bin[0]; l; l = ll) {
+    ll = l;
+    a_free(s->a, l->p);
+    a_free(s->a, l);
+  }
+  s->bin[0] = 0;
+
+#else
+
   size_t i;
   for (i = 0; i < SUB_BINS; i++) {
     void *p = s->bin[i];
@@ -144,23 +153,48 @@ void subarena_destroy(subarena *s)
       p = *(void **)q;
       A_FREE(s->a, q);
     }
+    s->bin[i] = 0;
   }
+
+#endif
 }
 
 /* --- @subarena_alloc@ --- *
  *
- * Arguments:   @subarena *s@ = pointer to arena
+ * Arguments:  @subarena *s@ = pointer to arena
  *             @size_t s@ = size of chunk wanted
  *
- * Returns:     Pointer to a block at least as large as the one wanted.
+ * Returns:    Pointer to a block at least as large as the one wanted.
  *
- * Use:         Allocates a small block of memory from the given pool.  The
+ * Use:                Allocates a small block of memory from the given pool.  The
  *             exception @EXC_NOMEM@ is raised if the underlying arena is
  *             full.
  */
 
 void *subarena_alloc(subarena *s, size_t sz)
 {
+#ifdef SUBARENA_TRIVIAL
+
+  sub_link *l;
+  void *p;
+
+  if (!s->a)
+    subarena_create(s, arena_global);
+
+  if ((l = a_alloc(s->a, sizeof(*l))) == 0)
+    return (0);
+  if ((p = a_alloc(s->a, sz)) == 0) {
+    a_free(s->a, l);
+    return (0);
+  }
+  l->p = p;
+  l->sz = sz;
+  l->next = s->bin[0];
+  s->bin[0] = l;
+  return (p);
+
+#else
+
   int bin;
   void *p;
 
@@ -168,10 +202,10 @@ void *subarena_alloc(subarena *s, size_t sz)
 
   if (!s->a)
     subarena_create(s, arena_global);
-  bin = SUB_BIN(sz);
 
   /* --- Handle oversize blocks --- */
 
+  bin = SUB_BIN(sz);
   if (bin >= SUB_BINS) {
     void *p = A_ALLOC(s->a, sz);
     if (!p)
@@ -207,21 +241,39 @@ void *subarena_alloc(subarena *s, size_t sz)
   p = s->bin[bin];
   s->bin[bin] = *(void **)p;
   return (p);
+
+#endif
 }
 
 /* --- @subarena_free@ --- *
  *
- * Arguments:   @subarena *s@ = pointer to arena
+ * Arguments:  @subarena *s@ = pointer to arena
  *             @void *p@ = address of block to free
- *              @size_t s@ = size of block
+ *             @size_t s@ = size of block
  *
- * Returns:     ---
+ * Returns:    ---
  *
- * Use:         Frees a block allocated by @subarena_alloc@.
+ * Use:                Frees a block allocated by @subarena_alloc@.
  */
 
 void subarena_free(subarena *s, void *p, size_t sz)
 {
+#ifdef SUBARENA_TRIVIAL
+
+  sub_link *lh = s->bin[0], **l, *ll;
+
+  for (l = &lh; *l && (*l)->p != p; l = &(*l)->next)
+    ;
+  ll = *l;
+  assert(ll);
+  assert(ll->sz == sz);
+  *l = ll->next;
+  a_free(s->a, ll);
+  a_free(s->a, p);
+  s->bin[0] = lh;
+
+#else
+
   int bin = SUB_BIN(sz);
 
   if (bin >= SUB_BINS)
@@ -230,44 +282,47 @@ void subarena_free(subarena *s, void *p, size_t sz)
     *(void **)p = s->bin[bin];
     s->bin[bin] = p;
   }
+
+#endif
 }
 
 /*----- Compatibility stuff -----------------------------------------------*/
 
 /* --- @sub_alloc@ --- *
  *
- * Arguments:   @size_t s@ = size of chunk wanted
+ * Arguments:  @size_t s@ = size of chunk wanted
  *
- * Returns:     Pointer to a block at least as large as the one wanted.
+ * Returns:    Pointer to a block at least as large as the one wanted.
  *
- * Use:         Allocates a small block of memory from the @sub_global@ pool.
+ * Use:                Allocates a small block of memory from the @sub_global@ pool.
  */
 
 void *(sub_alloc)(size_t sz) { return sub_alloc(sz); }
 
 /* --- @sub_free@ --- *
  *
- * Arguments:   @void *p@ = address of block to free
- *              @size_t s@ = size of block
+ * Arguments:  @void *p@ = address of block to free
+ *             @size_t s@ = size of block
  *
- * Returns:     ---
+ * Returns:    ---
  *
- * Use:         Frees a block allocated by @sub_alloc@.
+ * Use:                Frees a block allocated by @sub_alloc@.
  */
 
 void (sub_free)(void *p, size_t sz) { sub_free(p, sz); }
 
 /* --- @sub_init@ --- *
  *
- * Arguments:   ---
+ * Arguments:  ---
  *
- * Returns:     ---
+ * Returns:    ---
  *
- * Use:         Initializes the magic allocator.
+ * Use:                Initializes the magic allocator.
  */
 
 void sub_init(void)
 {
+#ifndef SUBARENA_TRIVIAL
   int i;
 
   /* --- Initialize the sizes bins --- */
@@ -276,6 +331,7 @@ void sub_init(void)
     sizes[i] = ((SUB_CHUNK + SUB_BINSZ(i) - 1) /
                     SUB_BINSZ(i) * SUB_BINSZ(i));
   }
+#endif
 }
 
 /*----- Debugging code ----------------------------------------------------*/