+++ /dev/null
-/* -*-c-*-
- *
- * 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.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <string.h>
-
-#include "align.h"
-#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;
-
- /* --- 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.
- */
-
- ALIGN(sz);
- 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 = sizeof(pool_chunk);
- ALIGN(ssz);
- csz = (ssz + sz + POOL_CHUNKSZ - 1); csz -= csz % POOL_CHUNKSZ;
- c = 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);
-}
-
-/* --- @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_init@ --- *
- *
- * Arguments: @pool *p@ = pointer to the pool structure to initialize
- * @arena *a@ = pointer to an arena to allocate memory from
- *
- * Returns: ---
- *
- * Use: Initializes a chunk of memory as a resource pool which is not
- * a child of any other resource pool.
- */
-
-void pool_init(pool *p, arena *a)
-{
- p->a.ops = &pool_ops;
- p->c = 0;
- p->r = 0;
- p->pa = a;
-}
-
-/* --- @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));
- pool_init(p, a);
- p->c = c;
- 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 pool created by @pool_create@, its memory will be
- * deallocated; if it's a subpool or it was initialized by
- * @pool_init@, 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 -------------------------------------------------*/