Commit f5c687f7 authored by Martin Mares's avatar Martin Mares
Browse files

Added lp_flush() which flushes contents of a linear pool, leaving all the

memory available for subsequent allocations from the same pool. Both flushing
and re-using the memory costs just few instructions.
parent f54801ff
Loading
Loading
Loading
Loading
+40 −11
Original line number Diff line number Diff line
/*
 *	BIRD Resource Manager -- Memory Pools
 *
 *	(c) 1998 Martin Mares <mj@ucw.cz>
 *	(c) 1998--1999 Martin Mares <mj@ucw.cz>
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */
@@ -20,8 +20,9 @@ struct lp_chunk {
struct linpool {
  resource r;
  byte *ptr, *end;
  struct lp_chunk *first, **plast;
  unsigned chunk_size, threshold, total;
  struct lp_chunk *first, *current, **plast;	/* Normal (reusable) chunks */
  struct lp_chunk *first_large;			/* Large chunks */
  unsigned chunk_size, threshold, total, total_large;
};

void lp_free(resource *);
@@ -39,11 +40,12 @@ linpool
{
  linpool *m = ralloc(p, &lp_class);
  m->ptr = m->end = NULL;
  m->first = NULL;
  m->first = m->current = NULL;
  m->plast = &m->first;
  m->first_large = NULL;
  m->chunk_size = blk;
  m->threshold = 3*blk/4;
  m->total = 0;
  m->total = m->total_large = 0;
  return m;
}

@@ -63,19 +65,30 @@ lp_alloc(linpool *m, unsigned size)
      struct lp_chunk *c;
      if (size >= m->threshold)
	{
	  /* Too large => allocate large chunk */
	  c = xmalloc(sizeof(struct lp_chunk) + size);
	  m->total += size;
	  m->total_large += size;
	  c->next = m->first_large;
	  m->first_large = c->next;
	}
      else
	{
	  if (m->current && m->current->next)
	    /* Still have free chunks from previous incarnation (before lp_flush()) */
	    c = m->current->next;
	  else
	    {
	      /* Need to allocate a new chunk */
	      c = xmalloc(sizeof(struct lp_chunk) + m->chunk_size);
	  m->ptr = c->data + size;
	  m->end = c->data + m->chunk_size;
	      m->total += m->chunk_size;
	}
	      *m->plast = c;
	      m->plast = &c->next;
	      c->next = NULL;
	    }
	  m->current = c;
	  m->ptr = c->data + size;
	  m->end = c->data + m->chunk_size;
	}
      return c->data;
    }
}
@@ -103,6 +116,22 @@ lp_allocz(linpool *m, unsigned size)
  return z;
}

void
lp_flush(linpool *m)
{
  struct lp_chunk *c;

  /* Relink all normal chunks to free list and free all large chunks */
  m->ptr = m->end = NULL;
  m->current = m->first;
  while (c = m->first_large)
    {
      m->first_large = c->next;
      xfree(c);
    }
  m->total_large = 0;
}

void
lp_free(resource *r)
{
+2 −1
Original line number Diff line number Diff line
/*
 *	BIRD Resource Manager
 *
 *	(c) 1998 Martin Mares <mj@ucw.cz>
 *	(c) 1998--1999 Martin Mares <mj@ucw.cz>
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */
@@ -54,6 +54,7 @@ linpool *lp_new(pool *, unsigned blk);
void *lp_alloc(linpool *, unsigned size);	/* Aligned */
void *lp_allocu(linpool *, unsigned size);	/* Unaligned */
void *lp_allocz(linpool *, unsigned size);	/* With clear */
void lp_flush(linpool *);			/* Free everything, but leave linpool */

/* Slabs */