Function mmem_exit releases memory used by the freelists.
[yaz-moved-to-github.git] / util / nmem.c
1 /*
2  * Copyright (c) 1995-1997, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: nmem.c,v $
7  * Revision 1.5  1997-10-06 09:09:52  adam
8  * Function mmem_exit releases memory used by the freelists.
9  *
10  * Revision 1.4  1997/09/29 07:12:50  adam
11  * NMEM thread safe. NMEM must be initialized before use (sigh) -
12  * routine nmem_init/nmem_exit implemented.
13  *
14  * Revision 1.3  1997/07/21 12:47:38  adam
15  * Moved definition of nmem_control and nmem_block.
16  *
17  * Revision 1.2  1995/12/13 13:44:37  quinn
18  * Modified Data1-system to use nmem
19  *
20  * Revision 1.1  1995/11/13  09:27:52  quinn
21  * Fiddling with the variant stuff.
22  *
23  *
24  */
25
26 /*
27  * This is a simple and fairly wasteful little module for nibble memory
28  * allocation. Evemtually we'll put in something better.
29  */
30
31 #include <xmalloc.h>
32 #include <nmem.h>
33 #ifdef WINDOWS
34 #include <windows.h>
35 #endif
36
37 #define NMEM_CHUNK (10*1024)
38
39 #ifdef WINDOWS
40 static CRITICAL_SECTION critical_section;
41 #define NMEM_ENTER EnterCriticalSection(&critical_section)
42 #define NMEM_LEAVE LeaveCriticalSection(&critical_section)
43 #else
44 #define NMEM_ENTER
45 #define NMEM_LEAVE
46 #endif
47
48 static nmem_block *freelist = NULL;        /* "global" freelists */
49 static nmem_control *cfreelist = NULL;
50
51 static void free_block(nmem_block *p)
52 {  
53     p->next = freelist;
54     freelist = p;
55 }
56
57 /*
58  * acquire a block with a minimum of size free bytes.
59  */
60 static nmem_block *get_block(int size)
61 {
62     nmem_block *r, *l;
63
64     for (r = freelist, l = 0; r; l = r, r = r->next)
65         if (r->size >= size)
66             break;
67     if (r)
68         if (l)
69             l->next = r->next;
70         else
71             freelist = r->next;
72     else
73     {
74         int get = NMEM_CHUNK;
75
76         if (get < size)
77             get = size;
78         r = xmalloc(sizeof(*r));
79         r->buf = xmalloc(r->size = get);
80     }
81     r->top = 0;
82     return r;
83 }
84
85 void nmem_reset(NMEM n)
86 {
87     nmem_block *t;
88
89     if (!n)
90         return;
91     NMEM_ENTER;
92     while (n->blocks)
93     {
94         t = n->blocks;
95         n->blocks = n->blocks->next;
96         free_block(t);
97     }
98     NMEM_LEAVE;
99     n->total = 0;
100 }
101
102 void *nmem_malloc(NMEM n, int size)
103 {
104     struct nmem_block *p;
105     char *r;
106
107     if (!n)
108         return xmalloc(size);
109     NMEM_ENTER;
110     p = n->blocks;
111     if (!p || p->size - p->top < size)
112     {
113         p = get_block(size);
114         p->next = n->blocks;
115         n->blocks = p;
116     }
117     r = p->buf + p->top;
118     /* align size */
119     p->top += (size + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
120     n->total += size;
121     NMEM_LEAVE;
122     return r;
123 }
124
125 int nmem_total(NMEM n)
126 {
127     return n->total;
128 }
129
130 NMEM nmem_create(void)
131 {
132     NMEM r;
133     
134     NMEM_ENTER;
135     r = cfreelist;
136     if (r)
137         cfreelist = cfreelist->next;
138     else
139         r = xmalloc(sizeof(*r));
140     NMEM_LEAVE;
141     r->blocks = 0;
142     r->total = 0;
143     r->next = 0;
144     return r;
145 }
146
147 void nmem_destroy(NMEM n)
148 {
149     if (!n)
150         return;
151     nmem_reset(n);
152     NMEM_ENTER;
153     n->next = cfreelist;
154     cfreelist = n;
155     NMEM_LEAVE;
156 }
157
158 void nmem_init (void)
159 {
160 #ifdef WINDOWS
161     InitializeCriticalSection(&critical_section);
162 #endif
163     freelist = NULL;
164     cfreelist = NULL;
165 }
166
167 void nmem_exit (void)
168 {
169     while (freelist)
170     {
171         struct nmem_block *fl = freelist;
172         freelist = freelist->next;
173         xfree (fl->buf);
174         xfree (fl);
175     }
176     while (cfreelist)
177     {
178         struct nmem_control *cfl = cfreelist;
179         cfreelist = cfreelist->next;
180         xfree (cfl);
181     }
182 #ifdef WINDOWS
183     DeleteCriticalSection(&critical_section);
184 #endif
185 }
186