2002-02-19 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mono / metadata / mempool.c
1 /*
2  * mempool.c: efficient memory allocation
3  *
4  * MonoMemPool is for fast allocation of memory. We free
5  * all memory when the pool is destroyed.
6  *
7  * Author:
8  *   Dietmar Maurer (dietmar@ximian.com)
9  *
10  * (C) 2001 Ximian, Inc.
11  */
12
13 #include <config.h>
14 #include <glib.h>
15 #include <string.h>
16
17 #include "mempool.h"
18
19 /*
20  * MonoMemPool is for fast allocation of memory. We free
21  * all memory when the pool is destroyed.
22  */
23
24 #if SIZEOF_VOID_P > SIZEOF_LONG
25 #define MEM_ALIGN     SIZEOF_VOID_P
26 #else
27 #define MEM_ALIGN     SIZEOF_LONG
28 #endif
29
30 #define MONO_MEMPOOL_PAGESIZE 8192
31
32 struct _MonoMemPool {
33         MonoMemPool *next;
34         gint rest;
35         gpointer pos;
36 };
37
38 /**
39  * mono_mempool_new:
40  *
41  * Returns: a new memory pool.
42  */
43 MonoMemPool *
44 mono_mempool_new ()
45 {
46
47         MonoMemPool *pool = g_malloc (MONO_MEMPOOL_PAGESIZE);
48         pool->next = NULL;
49         pool->pos = (gpointer)pool + sizeof (MonoMemPool);
50         pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool);
51         return pool;
52 }
53
54 /**
55  * mono_mempool_destroy:
56  * @pool: the momory pool to destroy
57  *
58  * Free all memory associated with this pool.
59  */
60 void
61 mono_mempool_destroy (MonoMemPool *pool)
62 {
63         MonoMemPool *p, *n;
64
65         p = pool;
66         while (p) {
67                 n = p->next;
68                 g_free (p);
69                 p = n;
70         }
71 }
72
73 /**
74  * mono_mempool_alloc:
75  * @pool: the momory pool to destroy
76  * @size: size of the momory block
77  *
78  * Allocates a new block of memory in @pool. @size must 
79  * be smaller than 256.
80  *
81  * Returns: the address of a newly allocated memory block.
82  */
83 gpointer
84 mono_mempool_alloc (MonoMemPool *pool, guint size)
85 {
86         gpointer rval;
87         
88         g_assert (pool != NULL);
89
90         if (size >= 4096) {
91                 MonoMemPool *np = g_malloc (sizeof (MonoMemPool) + size);
92                 np->next = pool->next;
93                 pool->next = np;
94                 return (gpointer)np + sizeof (MonoMemPool);
95         }
96
97         size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1);
98
99         if (pool->rest < size) {
100                 MonoMemPool *np = g_malloc (MONO_MEMPOOL_PAGESIZE);
101                 np->next = pool->next;
102                 pool->next = np;
103                 pool->pos = (gpointer)np + sizeof (MonoMemPool);
104                 pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool);
105         }
106
107         rval = pool->pos;
108         pool->rest -= size;
109         pool->pos += size;
110
111         return rval;
112 }
113
114 /**
115  * mono_mempool_alloc0:
116  *
117  * same as mono_mempool_alloc, but fills memory with zero.
118  */
119 gpointer
120 mono_mempool_alloc0 (MonoMemPool *pool, guint size)
121 {
122         gpointer rval = mono_mempool_alloc (pool, size);
123         memset (rval, 0, size);
124         return rval;
125 }
126