chiark / gitweb /
Support for resource pools, based on the Apache model.
authormdw <mdw>
Sun, 16 Jul 2000 12:28:48 +0000 (12:28 +0000)
committermdw <mdw>
Sun, 16 Jul 2000 12:28:48 +0000 (12:28 +0000)
pool-file.c [new file with mode: 0644]
pool-sub.c [new file with mode: 0644]
pool.c [new file with mode: 0644]
pool.h [new file with mode: 0644]

diff --git a/pool-file.c b/pool-file.c
new file mode 100644 (file)
index 0000000..304fa3b
--- /dev/null
@@ -0,0 +1,92 @@
+/* -*-c-*-
+ *
+ * $Id: pool-file.c,v 1.1 2000/07/16 12:28:48 mdw Exp $
+ *
+ * File handles in resource pools
+ *
+ * (c) 2000 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of the mLib utilities library.
+ *
+ * mLib is free software; you can redistribute it and/or modify
+ * 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: pool-file.c,v $
+ * Revision 1.1  2000/07/16 12:28:48  mdw
+ * Support for resource pools, based on the Apache model.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+
+#include "pool.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @pool_fopen@ --- *
+ *
+ * Arguments:  @pool *p@ = pointer to a pool
+ *             @const char *file@ = name of the file to open
+ *             @const char *how@ = string specifying opening parameters
+ *
+ * Returns:    A pointer to a pool resource containing an open file handle,
+ *             or null if the file open filed.
+ *
+ * Use:                Opens a file so that it will be freed again when a pool is
+ *             destroyed.
+ */
+
+static void pf_destroy(pool_resource *r) { pool_fclose((pool_file *)r); }
+
+pool_file *pool_fopen(pool *p, const char *file, const char *how)
+{
+  FILE *fp;
+  pool_file *pf;
+
+  if ((fp = fopen(file, how)) == 0)
+    return (0);
+  pf = pool_alloc(p, sizeof(pool_file));
+  POOL_ADD(p, &pf->r, pf_destroy);
+  pf->fp = fp;
+  return (pf);
+}
+
+/* --- @pool_fclose@ --- *
+ *
+ * Arguments:  @pool_file *pf@ = pointer to a file resource
+ *
+ * Returns:    The response from the @fclose@ function.
+ *
+ * Use:                Closes a file.  It is not an error to close a file multiple
+ *             times.
+ */
+
+int pool_fclose(pool_file *pf)
+{
+  if (!pf->r.destroy)
+    return (0);
+  pf->r.destroy = 0;
+  return (fclose(pf->fp));
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pool-sub.c b/pool-sub.c
new file mode 100644 (file)
index 0000000..1ebd5b6
--- /dev/null
@@ -0,0 +1,63 @@
+/* -*-c-*-
+ *
+ * $Id: pool-sub.c,v 1.1 2000/07/16 12:28:48 mdw Exp $
+ *
+ * Subarenas in resource pools
+ *
+ * (c) 2000 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of the mLib utilities library.
+ *
+ * mLib is free software; you can redistribute it and/or modify
+ * 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: pool-sub.c,v $
+ * Revision 1.1  2000/07/16 12:28:48  mdw
+ * Support for resource pools, based on the Apache model.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "pool.h"
+#include "sub.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @pool_subarena@ --- *
+ *
+ * Arguments:  @pool *p@ = pointer to the pool
+ *
+ * Returns:    A subarena built from the pool's memory allocator.
+ *
+ * Use:                Creates a suballocation arena attached to a pool.  The arena
+ *             and all of its memory will be freed when the pool is
+ *             destroyed.
+ */
+
+subarena *pool_subarena(pool *p)
+{
+  subarena *sa = pool_alloc(p, sizeof(subarena));
+  subarena_create(sa, &p->a);
+  return (sa);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pool.c b/pool.c
new file mode 100644 (file)
index 0000000..0c4e3ed
--- /dev/null
+++ b/pool.c
@@ -0,0 +1,279 @@
+/* -*-c-*-
+ *
+ * $Id: pool.c,v 1.1 2000/07/16 12:28:48 mdw Exp $
+ *
+ * Resource pool handling
+ *
+ * (c) 2000 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of the mLib utilities library.
+ *
+ * mLib is free software; you can redistribute it and/or modify
+ * 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: pool.c,v $
+ * Revision 1.1  2000/07/16 12:28:48  mdw
+ * Support for resource pools, based on the Apache model.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "alloc.h"
+#include "arena.h"
+#include "pool.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @doalloc@ --- *
+ *
+ * Arguments:  @arena *a@ = pointer to arena to allocate memory from
+ *             @pool_chunk **cc@ = pointer to chunk list
+ *             @size_t sz@ = size of memory wanted
+ *
+ * Returns:    Pointer to the allocated block.
+ *
+ * Use:                The basic allocator for resource pools.  This is also used
+ *             during pool creation, hence the slightly bizarre interface.
+ */
+
+static void *doalloc(arena *a, pool_chunk **cc, size_t sz)
+{
+  pool_chunk *c;
+  void *p;
+  size_t csz, ssz;
+
+  /* --- Round up the requested size --- *
+   *
+   * This assumes too much about how various objects are aligned.  It could
+   * do with improvement some time.  This is, I believe, the only
+   * nonportability in the code, and it should work on `sane' architectures
+   * anyway.
+   */
+
+#define ROUNDUP(sz) ((sz + 15) % 16)
+
+  sz = ROUNDUP(sz);
+
+  /* --- See if there's enough space --- *
+   *
+   * The chunks are sorted by available space, so if there's not enough space
+   * in the first chunk there isn't enough space anywhere.
+   */
+
+  c = *cc;
+  if (c && c->left >= sz) {
+    p = c->p;
+    c->p += sz;
+    c->left -= sz;
+    *cc = c->next;
+  }
+
+  /* --- Failed to find anything --- *
+   *
+   * I must allocate a new block from the arena, then.
+   */
+
+  else {
+    ssz = ROUNDUP(sizeof(pool_chunk));
+    csz = (ssz + sz + POOL_CHUNKSZ - 1) % POOL_CHUNKSZ;
+    p = x_alloc(a, csz);
+    p = (char *)c + ssz;
+    c->p = (char *)p + sz;
+    c->left = csz - ssz - sz;
+  }
+
+  /* --- Move this chunk in the list so that it's sorted --- */
+
+  while (*cc && (*cc)->left > c->left)
+    cc = &(*cc)->next;
+  c->next = *cc;
+  *cc = c;
+
+  /* --- Done --- */
+
+  return (p);
+
+#undef ROUNDUP
+}
+
+/* --- @pool_alloc@ --- *
+ *
+ * Arguments:  @pool *p@ = pool to allocate from
+ *             @size_t sz@ = size of block wanted
+ *
+ * Returns:    Pointer to the requested block.
+ *
+ * Use:                Allocates memory from a resource pool.  Memory is never freed
+ *             from pools: it is released when the pool is destroyed.
+ */
+
+void *pool_alloc(pool *p, size_t sz)
+{
+  return (doalloc(p->pa, &p->c, sz));
+}
+
+/* --- @pool_strdup@ --- *
+ *
+ * Arguments:  @pool *p@ = pool to allocate from
+ *             @const char *s@ = pointer to string
+ *
+ * Returns:    A pointer to a copy of the string.
+ *
+ * Use:                Allocates a copy of a string.
+ */
+
+char *pool_strdup(pool *p, const char *s)
+{
+  size_t sz = strlen(s) + 1;
+  char *pp = doalloc(p->pa, &p->c, sz);
+  memcpy(pp, s, sz);
+  return (pp);
+}
+
+/* --- Arena operations --- */
+
+static void *palloc(arena *a, size_t sz)
+{
+  pool *p = (pool *)a;
+  return (doalloc(p->pa, &p->c, sz));
+}
+
+static void pfree(arena *a, void *p) { return; } /* Trivial */
+
+static arena_ops pool_ops = { palloc, arena_fakerealloc, pfree, 0 };
+
+/* --- @pool_create@ --- *
+ *
+ * Arguments:  @arena *a@ = pointer to an arena to allocate memory from
+ *
+ * Returns:    A newly created resource pool.
+ *
+ * Use:                Creates a resource pool which is not a child of any other
+ *             resource pool.
+ */
+
+pool *pool_create(arena *a)
+{
+  pool_chunk *c = 0;
+  pool *p = doalloc(a, &c, sizeof(pool));
+  p->a.ops = &pool_ops;
+  p->c = c;
+  p->r = 0;
+  p->pa = a;
+  return (p);
+}
+
+/* --- @pool_destroy@ --- *
+ *
+ * Arguments:  @pool *p@ = pointer to pool to destroy
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a pool, freeing all of the resources within it.  If
+ *             this is a root pool, its memory will be deallocated; if it's
+ *             a subpool, it is emptied and can be used again.
+ */
+
+void pool_destroy(pool *p)
+{
+  pool_resource *r, *rr;
+  arena *a;
+  pool_chunk *c, *cc;
+
+  /* --- Dispose of all of the resources --- */
+
+  r = p->r;
+  while (r) {
+    rr = r->next;
+    if (r->destroy)
+      r->destroy(r);
+    r = rr;
+  }
+  p->r = 0;
+
+  /* --- Free all of the memory --- *
+   *
+   * Since root pools are allocated in their own memory, this will free the
+   * root pool block.  Subpools are allocated in their parent's memory, so
+   * the pool block itself will be left around.
+   */
+
+  a = p->pa;
+  c = p->c;
+  p->c = 0;
+  while (c) {
+    cc = c->next;
+    x_free(a, c);
+    c = cc;
+  }
+}
+
+/* --- @pool_add@ --- *
+ *
+ * Arguments:  @pool *p@ = pointer to pool to add the resource to
+ *             @pool_resource *r@ = pointer to resource block
+ *             @void (*dfn)(pool_resource *r)@ = destruction function
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds a resource to a pool.
+ */
+
+void pool_add(pool *p, pool_resource *r, void (*dfn)(pool_resource *r))
+{
+  POOL_ADD(p, r, dfn);
+}
+
+/* --- @pool_sub@ --- *
+ *
+ * Arguments:  @pool *p@ = pointer to parent pool
+ *
+ * Returns:    A new child pool of the parent.
+ *
+ * Use:                Creates a subpool.  The subpool can either be destroyed on
+ *             its own, or will be automatically destroyed at the same time
+ *             as the parent.
+ */
+
+typedef struct subpool {
+  pool_resource r;
+  pool p;
+} subpool;
+
+static void subpool_destroy(pool_resource *r)
+{
+  subpool *p = (subpool *)r;
+  pool_destroy(&p->p);
+}
+
+pool *pool_sub(pool *p)
+{
+  subpool *pp = pool_alloc(p, sizeof(subpool));
+  POOL_ADD(p, &pp->r, subpool_destroy);
+  pp->p.a.ops = &pool_ops;
+  pp->p.c = 0;
+  pp->p.r = 0;
+  pp->p.pa = p->pa;
+  return (&pp->p);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/pool.h b/pool.h
new file mode 100644 (file)
index 0000000..973a4fc
--- /dev/null
+++ b/pool.h
@@ -0,0 +1,220 @@
+/* -*-c-*-
+ *
+ * $Id: pool.h,v 1.1 2000/07/16 12:28:48 mdw Exp $
+ *
+ * Resource pool handling
+ *
+ * (c) 2000 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of the mLib utilities library.
+ *
+ * mLib is free software; you can redistribute it and/or modify
+ * 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: pool.h,v $
+ * Revision 1.1  2000/07/16 12:28:48  mdw
+ * Support for resource pools, based on the Apache model.
+ *
+ */
+
+#ifndef MLIB_POOL_H
+#define MLIB_POOL_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+
+#ifndef MLIB_ARENA_H
+#  include "arena.h"
+#endif
+
+#ifndef MLIB_SUB_H
+#  include "sub.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+#define POOL_CHUNKSZ 65536
+
+typedef struct pool_chunk {
+  struct pool_chunk *next;             /* Next memory chunk in the chain */
+  char *p;                             /* Free area in this chunk */
+  size_t left;                         /* Amount of memory left */
+} pool_chunk;
+
+typedef struct pool_resource {
+  struct pool_resource *next;          /* Next resource in the chain */
+  void (*destroy)(struct pool_resource */*r*/); /* Destruction function */
+} pool_resource;
+
+typedef struct pool {
+  arena a;                             /* The arena for allocating memory */
+  pool_chunk *c;                       /* Pointer to memory chunk list */
+  pool_resource *r;                    /* Pointer to resource list */
+  arena *pa;                           /* Arena for real allocation */
+} pool;
+
+typedef struct pool_file {
+  pool_resource r;                     /* A pool resource record */
+  FILE *fp;                            /* The actual file handle */
+} pool_file;
+
+/*----- Basic pool management ---------------------------------------------*/
+
+/* --- @pool_alloc@ --- *
+ *
+ * Arguments:  @pool *p@ = pool to allocate from
+ *             @size_t sz@ = size of block wanted
+ *
+ * Returns:    Pointer to the requested block.
+ *
+ * Use:                Allocates memory from a resource pool.  Memory is never freed
+ *             from pools: it is released when the pool is destroyed.
+ */
+
+extern void *pool_alloc(pool */*p*/, size_t /*sz*/);
+
+/* --- @pool_strdup@ --- *
+ *
+ * Arguments:  @pool *p@ = pool to allocate from
+ *             @const char *s@ = pointer to string
+ *
+ * Returns:    A pointer to a copy of the string.
+ *
+ * Use:                Allocates a copy of a string.
+ */
+
+extern char *pool_strdup(pool */*p*/, const char */*s*/);
+
+/* --- @pool_create@ --- *
+ *
+ * Arguments:  @arena *a@ = pointer to an arena to allocate memory from
+ *
+ * Returns:    A newly created resource pool.
+ *
+ * Use:                Creates a resource pool which is not a child of any other
+ *             resource pool.
+ */
+
+extern pool *pool_create(arena */*a*/);
+
+/* --- @pool_destroy@ --- *
+ *
+ * Arguments:  @pool *p@ = pointer to pool to destroy
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys a pool, freeing all of the resources within it.  If
+ *             this is a root pool, its memory will be deallocated; if it's
+ *             a subpool, it is emptied and can be used again.
+ */
+
+extern void pool_destroy(pool */*p*/);
+
+/* --- @pool_sub@ --- *
+ *
+ * Arguments:  @pool *p@ = pointer to parent pool
+ *
+ * Returns:    A new child pool of the parent.
+ *
+ * Use:                Creates a subpool.  The subpool can either be destroyed on
+ *             its own, or will be automatically destroyed at the same time
+ *             as the parent.
+ */
+
+extern pool *pool_sub(pool */*p*/);
+
+/* --- @pool_add@ --- *
+ *
+ * Arguments:  @pool *p@ = pointer to pool to add the resource to
+ *             @pool_resource *r@ = pointer to resource block
+ *             @void (*dfn)(pool_resource *r)@ = destruction function
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds a resource to a pool.
+ */
+
+#define POOL_ADD(p, rr, dfn) do {                                      \
+  pool *_p = (p);                                                      \
+  pool_resource *_r = (rr);                                            \
+  _r->next = _p->r;                                                    \
+  _r->destroy = dfn;                                                   \
+  _p->r = _r;                                                          \
+} while (0)
+
+extern void pool_add(pool */*p*/, pool_resource */*r*/,
+                    void (*/*dfn*/)(pool_resource */*r*/));
+
+/*----- Various simple resource types -------------------------------------*/
+
+/* --- @pool_fopen@ --- *
+ *
+ * Arguments:  @pool *p@ = pointer to a pool
+ *             @const char *file@ = name of the file to open
+ *             @const char *how@ = string specifying opening parameters
+ *
+ * Returns:    A pointer to a pool resource containing an open file handle,
+ *             or null if the file open filed.
+ *
+ * Use:                Opens a file so that it will be freed again when a pool is
+ *             destroyed.
+ */
+
+extern pool_file *pool_fopen(pool */*p*/,
+                            const char */*file*/, const char */*how*/);
+
+/* --- @pool_fclose@ --- *
+ *
+ * Arguments:  @pool_file *pf@ = pointer to a file resource
+ *
+ * Returns:    The response from the @fclose@ function.
+ *
+ * Use:                Closes a file.  It is not an error to close a file multiple
+ *             times.
+ */
+
+extern int pool_fclose(pool_file */*pf*/);
+
+/* --- @pool_subarena@ --- *
+ *
+ * Arguments:  @pool *p@ = pointer to the pool
+ *
+ * Returns:    A subarena built from the pool's memory allocator.
+ *
+ * Use:                Creates a suballocation arena attached to a pool.  The arena
+ *             and all of its memory will be freed when the pool is
+ *             destroyed.
+ */
+
+extern subarena *pool_subarena(pool */*p*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif