Minor change to make C++ happy.
[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.7  1998-02-11 11:53:36  adam
8  * Changed code so that it compiles as C++.
9  *
10  * Revision 1.6  1997/10/31 12:20:09  adam
11  * Improved memory debugging for xmalloc/nmem.c. References to NMEM
12  * instead of ODR in n ESPEC-1 handling in source d1_espec.c.
13  * Bug fix: missing fclose in data1_read_espec1.
14  *
15  * Revision 1.5  1997/10/06 09:09:52  adam
16  * Function mmem_exit releases memory used by the freelists.
17  *
18  * Revision 1.4  1997/09/29 07:12:50  adam
19  * NMEM thread safe. NMEM must be initialized before use (sigh) -
20  * routine nmem_init/nmem_exit implemented.
21  *
22  * Revision 1.3  1997/07/21 12:47:38  adam
23  * Moved definition of nmem_control and nmem_block.
24  *
25  * Revision 1.2  1995/12/13 13:44:37  quinn
26  * Modified Data1-system to use nmem
27  *
28  * Revision 1.1  1995/11/13  09:27:52  quinn
29  * Fiddling with the variant stuff.
30  *
31  *
32  */
33
34 /*
35  * This is a simple and fairly wasteful little module for nibble memory
36  * allocation. Evemtually we'll put in something better.
37  */
38
39 #include <xmalloc.h>
40 #include <nmem.h>
41 #include <log.h>
42 #ifdef WINDOWS
43 #include <windows.h>
44 #endif
45
46 #define NMEM_CHUNK (10*1024)
47
48 #ifdef WINDOWS
49 static CRITICAL_SECTION critical_section;
50 #define NMEM_ENTER EnterCriticalSection(&critical_section)
51 #define NMEM_LEAVE LeaveCriticalSection(&critical_section)
52 #else
53 #define NMEM_ENTER
54 #define NMEM_LEAVE
55 #endif
56
57 static nmem_block *freelist = NULL;        /* "global" freelists */
58 static nmem_control *cfreelist = NULL;
59 static int nmem_active_no = 0;
60
61 static void free_block(nmem_block *p)
62 {  
63     p->next = freelist;
64     freelist = p;
65 }
66
67 /*
68  * acquire a block with a minimum of size free bytes.
69  */
70 static nmem_block *get_block(int size)
71 {
72     nmem_block *r, *l;
73
74     for (r = freelist, l = 0; r; l = r, r = r->next)
75         if (r->size >= size)
76             break;
77     if (r)
78         if (l)
79             l->next = r->next;
80         else
81             freelist = r->next;
82     else
83     {
84         int get = NMEM_CHUNK;
85
86         if (get < size)
87             get = size;
88         r = (nmem_block *)xmalloc(sizeof(*r));
89         r->buf = (char *)xmalloc(r->size = get);
90     }
91     r->top = 0;
92     return r;
93 }
94
95 void nmem_reset(NMEM n)
96 {
97     nmem_block *t;
98
99     if (!n)
100         return;
101     NMEM_ENTER;
102     while (n->blocks)
103     {
104         t = n->blocks;
105         n->blocks = n->blocks->next;
106         free_block(t);
107     }
108     NMEM_LEAVE;
109     n->total = 0;
110 }
111
112 void *nmem_malloc(NMEM n, int size)
113 {
114     struct nmem_block *p;
115     char *r;
116
117     if (!n)
118         return xmalloc(size);
119     NMEM_ENTER;
120     p = n->blocks;
121     if (!p || p->size - p->top < size)
122     {
123         p = get_block(size);
124         p->next = n->blocks;
125         n->blocks = p;
126     }
127     r = p->buf + p->top;
128     /* align size */
129     p->top += (size + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
130     n->total += size;
131     NMEM_LEAVE;
132     return r;
133 }
134
135 int nmem_total(NMEM n)
136 {
137     return n->total;
138 }
139
140 #if NMEM_DEBUG
141 NMEM nmem_create_f(const char *file, int line)
142 #else
143 NMEM nmem_create(void)
144 #endif
145 {
146     NMEM r;
147     
148     NMEM_ENTER;
149     nmem_active_no++;
150     r = cfreelist;
151     if (r)
152         cfreelist = cfreelist->next;
153     else
154         r = (nmem_control *)xmalloc(sizeof(*r));
155     NMEM_LEAVE;
156
157 #if NMEM_DEBUG
158     logf (LOG_DEBUG, "%s:%d: nmem_create %d p=%p", file, line,
159                      nmem_active_no-1, r);
160 #endif
161     r->blocks = 0;
162     r->total = 0;
163     r->next = 0;
164     return r;
165 }
166
167 #if NMEM_DEBUG
168 void nmem_destroy_f(const char *file, int line, NMEM n)
169 #else
170 void nmem_destroy(NMEM n)
171 #endif
172 {
173     if (!n)
174         return;
175     nmem_reset(n);
176     NMEM_ENTER;
177     nmem_active_no--;
178     n->next = cfreelist;
179     cfreelist = n;
180     NMEM_LEAVE;
181 #if NMEM_DEBUG
182     logf (LOG_DEBUG, "%s:%d: nmem_destroy %d p=%p", file, line,
183                      nmem_active_no, n);
184 #endif
185 }
186
187 void nmem_init (void)
188 {
189 #ifdef WINDOWS
190     InitializeCriticalSection(&critical_section);
191 #endif
192     nmem_active_no = 0;
193     freelist = NULL;
194     cfreelist = NULL;
195 }
196
197 void nmem_exit (void)
198 {
199     while (freelist)
200     {
201         struct nmem_block *fl = freelist;
202         freelist = freelist->next;
203         xfree (fl->buf);
204         xfree (fl);
205     }
206     while (cfreelist)
207     {
208         struct nmem_control *cfl = cfreelist;
209         cfreelist = cfreelist->next;
210         xfree (cfl);
211     }
212 #ifdef WINDOWS
213     DeleteCriticalSection(&critical_section);
214 #endif
215 }
216