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.
This commit is contained in:
Martin Mares 1999-03-29 19:35:47 +00:00
parent f54801ffed
commit f5c687f791
2 changed files with 42 additions and 12 deletions

View file

@ -1,7 +1,7 @@
/* /*
* BIRD Resource Manager -- Memory Pools * 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. * Can be freely distributed and used under the terms of the GNU GPL.
*/ */
@ -20,8 +20,9 @@ struct lp_chunk {
struct linpool { struct linpool {
resource r; resource r;
byte *ptr, *end; byte *ptr, *end;
struct lp_chunk *first, **plast; struct lp_chunk *first, *current, **plast; /* Normal (reusable) chunks */
unsigned chunk_size, threshold, total; struct lp_chunk *first_large; /* Large chunks */
unsigned chunk_size, threshold, total, total_large;
}; };
void lp_free(resource *); void lp_free(resource *);
@ -39,11 +40,12 @@ linpool
{ {
linpool *m = ralloc(p, &lp_class); linpool *m = ralloc(p, &lp_class);
m->ptr = m->end = NULL; m->ptr = m->end = NULL;
m->first = NULL; m->first = m->current = NULL;
m->plast = &m->first; m->plast = &m->first;
m->first_large = NULL;
m->chunk_size = blk; m->chunk_size = blk;
m->threshold = 3*blk/4; m->threshold = 3*blk/4;
m->total = 0; m->total = m->total_large = 0;
return m; return m;
} }
@ -63,19 +65,30 @@ lp_alloc(linpool *m, unsigned size)
struct lp_chunk *c; struct lp_chunk *c;
if (size >= m->threshold) if (size >= m->threshold)
{ {
/* Too large => allocate large chunk */
c = xmalloc(sizeof(struct lp_chunk) + size); 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 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); 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->total += m->chunk_size;
}
*m->plast = c; *m->plast = c;
m->plast = &c->next; m->plast = &c->next;
c->next = NULL; c->next = NULL;
}
m->current = c;
m->ptr = c->data + size;
m->end = c->data + m->chunk_size;
}
return c->data; return c->data;
} }
} }
@ -103,6 +116,22 @@ lp_allocz(linpool *m, unsigned size)
return z; 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 void
lp_free(resource *r) lp_free(resource *r)
{ {

View file

@ -1,7 +1,7 @@
/* /*
* BIRD Resource Manager * 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. * 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_alloc(linpool *, unsigned size); /* Aligned */
void *lp_allocu(linpool *, unsigned size); /* Unaligned */ void *lp_allocu(linpool *, unsigned size); /* Unaligned */
void *lp_allocz(linpool *, unsigned size); /* With clear */ void *lp_allocz(linpool *, unsigned size); /* With clear */
void lp_flush(linpool *); /* Free everything, but leave linpool */
/* Slabs */ /* Slabs */