/* ----------------------------------------------------------------------------- 
 * memory.c
 *
 *     This file implements all of DOH's memory management including allocation
 *     of objects and checking of objects.
 * 
 * Author(s) : David Beazley (beazley@cs.uchicago.edu)
 *
 * Copyright (C) 1999-2000.  The University of Chicago
 * See the file LICENSE for information on usage and redistribution.	
 * ----------------------------------------------------------------------------- */

char cvsroot_memory_c[] = "$Header: /cvsroot/CableSwig/CableSwig/SWIG/Source/DOH/Doh/memory.c,v 1.1.1.1 2003/04/09 17:34:10 hoffman Exp $";

#include "dohint.h"

#ifndef DOH_POOL_SIZE
#define DOH_POOL_SIZE         16384
#endif

static int   PoolSize = DOH_POOL_SIZE;

DOH    *DohNone = 0;    /* The DOH None object */

typedef struct pool {
  DohBase       *ptr;            /* Start of pool */
  int            len;            /* Length of pool */
  int            blen;           /* Byte length of pool */
  int            current;        /* Current position for next allocation */
  struct  pool  *next;           /* Next pool */
} Pool;

static DohBase  *FreeList = 0;          /* List of free objects */
static Pool    *Pools = 0;
static int      pools_initialized = 0;

/* ----------------------------------------------------------------------
 * CreatePool() - Create a new memory pool 
 * ---------------------------------------------------------------------- */

static void
CreatePool() {
  Pool *p = 0;
  p = (Pool *) DohMalloc(sizeof(Pool));
  assert(p);
  p->ptr = (DohBase *) DohMalloc(sizeof(DohBase)*PoolSize);
  assert(p->ptr);
  p->len = PoolSize;
  p->blen = PoolSize*sizeof(DohBase);
  p->current = 0;
  p->next = Pools;
  Pools = p;
}

/* ----------------------------------------------------------------------
 * InitPools() - Initialize the memory allocator
 * ---------------------------------------------------------------------- */

static void 
InitPools() {
  if (pools_initialized) return;
  CreatePool();                       /* Create initial pool */
  pools_initialized = 1;
  DohNone = NewVoid(0,0);             /* Create the None object */
  DohIntern(DohNone);
}

/* ----------------------------------------------------------------------
 * DohCheck()
 *
 * Returns 1 if an arbitrary pointer is a DOH object.
 * ---------------------------------------------------------------------- */

int 
DohCheck(const DOH *ptr) {
  Pool *p = Pools;
  register char *cptr = (char *) ptr;
  register char *pptr;
  while (p) {
    pptr = (char *) p->ptr;
    if ((cptr >= pptr) && (cptr < (pptr + p->blen))) return 1;
    /*
    pptr = (char *) p->ptr;
    if ((cptr >= pptr) && (cptr < (pptr+(p->current*sizeof(DohBase))))) return 1; */
    p = p->next;
  }
  return 0;
}

/* -----------------------------------------------------------------------------
 * DohIntern()
 * ----------------------------------------------------------------------------- */

void
DohIntern(DOH *obj) {
  DohBase *b = (DohBase *) obj;
  b->flag_intern = 1;
}

/* ----------------------------------------------------------------------
 * DohObjMalloc()
 *
 * Allocate memory for a new object.
 * ---------------------------------------------------------------------- */

DOH *
DohObjMalloc(DohObjInfo *type, void *data) {
  DohBase *obj;
  if (!pools_initialized) InitPools();
  if (FreeList) {
    obj = FreeList;
    FreeList = (DohBase *) obj->data;
  } else {
    while (Pools->current == Pools->len) {
      PoolSize *= 2;
      CreatePool();
    }
    obj = Pools->ptr + Pools->current;
    Pools->current++;
  }
  obj->type = type;
  obj->data = data;
  obj->meta = 0;
  obj->refcount = 1;
  obj->flag_intern = 0;
  obj->flag_marked = 0;
  obj->flag_user = 0;
  obj->flag_usermark = 0;
  return (DOH *) obj;
}

/* ----------------------------------------------------------------------
 * DohObjFree() - Free a DOH object
 * ---------------------------------------------------------------------- */

void 
DohObjFree(DOH *ptr) {
  DohBase  *b;
  b = (DohBase *) ptr;
  if (b->flag_intern) return;
  b->data = (void *) FreeList;
  if (b->meta) {
    Delete(b->meta);
    b->meta = 0;
  }
  b->type = 0;
  FreeList = b;
}
