]> mj.ucw.cz Git - libucw.git/blob - lib/pool.c
6143c68af0b67c5f2f87301b08e90773e8b31000
[libucw.git] / lib / pool.c
1 /*
2  *      Sherlock Library -- Memory Pools (One-Time Allocation)
3  *
4  *      (c) 1997--2001 Martin Mares <mj@ucw.cz>
5  */
6
7 #include "lib/lib.h"
8 #include "lib/pools.h"
9
10 #include <stdlib.h>
11
12 struct memchunk {
13   struct memchunk *next;
14   byte data[0];
15 };
16
17 struct mempool *
18 mp_new(uns size)
19 {
20   struct mempool *p = xmalloc(sizeof(struct mempool));
21
22   size -= sizeof(struct memchunk);
23   p->free = p->last = NULL;
24   p->first = p->current = p->first_large = NULL;
25   p->plast = &p->first;
26   p->chunk_size = size;
27   p->threshold = size / 3;
28   return p;
29 }
30
31 void
32 mp_delete(struct mempool *p)
33 {
34   struct memchunk *c, *d;
35
36   for(d=p->first; d; d = c)
37     {
38       c = d->next;
39       xfree(d);
40     }
41   for(d=p->first_large; d; d = c)
42     {
43       c = d->next;
44       xfree(d);
45     }
46   xfree(p);
47 }
48
49 void
50 mp_flush(struct mempool *p)
51 {
52   struct memchunk *c;
53
54   p->free = p->last = NULL;
55   p->current = p->first;
56   while (c = p->first_large)
57     {
58       p->first_large = c->next;
59       xfree(c);
60     }
61 }
62
63 void *
64 mp_alloc(struct mempool *p, uns s)
65 {
66   if (s <= p->threshold)
67     {
68       byte *x = (byte *)(((uns) p->free + POOL_ALIGN - 1) & ~(POOL_ALIGN - 1));
69       if (x + s > p->last)
70         {
71           struct memchunk *c;
72
73           if (p->current)
74             {
75               /* Still have free chunks from previous incarnation */
76               c = p->current;
77               p->current = c->next;
78             }
79           else
80             {
81               c = xmalloc(sizeof(struct memchunk) + p->chunk_size);
82               *p->plast = c;
83               p->plast = &c->next;
84               c->next = NULL;
85             }
86           x = c->data;
87           p->last = x + p->chunk_size;
88         }
89       p->free = x + s;
90       return x;
91     }
92   else
93     {
94       struct memchunk *c = xmalloc(sizeof(struct memchunk) + s);
95       c->next = p->first_large;
96       p->first_large = c;
97       return c->data;
98     }
99 }