1 | /*<html><pre> -<a href="qh-mem.htm"
|
---|
2 | >-------------------------------</a><a name="TOP">-</a>
|
---|
3 |
|
---|
4 | mem.c
|
---|
5 | memory management routines for qhull
|
---|
6 |
|
---|
7 | This is a standalone program.
|
---|
8 |
|
---|
9 | To initialize memory:
|
---|
10 |
|
---|
11 | qh_meminit(stderr);
|
---|
12 | qh_meminitbuffers(qh IStracing, qh_MEMalign, 7, qh_MEMbufsize,qh_MEMinitbuf);
|
---|
13 | qh_memsize((int)sizeof(facetT));
|
---|
14 | qh_memsize((int)sizeof(facetT));
|
---|
15 | ...
|
---|
16 | qh_memsetup();
|
---|
17 |
|
---|
18 | To free up all memory buffers:
|
---|
19 | qh_memfreeshort(&curlong, &totlong);
|
---|
20 |
|
---|
21 | if qh_NOmem,
|
---|
22 | malloc/free is used instead of mem.c
|
---|
23 |
|
---|
24 | notes:
|
---|
25 | uses Quickfit algorithm (freelists for commonly allocated sizes)
|
---|
26 | assumes small sizes for freelists (it discards the tail of memory buffers)
|
---|
27 |
|
---|
28 | see:
|
---|
29 | qh-mem.htm and mem.h
|
---|
30 | global.c (qh_initbuffers) for an example of using mem.c
|
---|
31 |
|
---|
32 | Copyright (c) 1993-2012 The Geometry Center.
|
---|
33 | $Id: //main/2011/qhull/src/libqhull/mem.c#4 $$Change: 1464 $
|
---|
34 | $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
|
---|
35 | */
|
---|
36 |
|
---|
37 | #include "mem.h"
|
---|
38 | #include <string.h>
|
---|
39 | #include <stdio.h>
|
---|
40 | #include <stdlib.h>
|
---|
41 |
|
---|
42 | #ifndef qhDEFlibqhull
|
---|
43 | typedef struct ridgeT ridgeT;
|
---|
44 | typedef struct facetT facetT;
|
---|
45 | #ifdef _MSC_VER /* Microsoft Visual C++ -- warning level 4 */
|
---|
46 | #pragma warning( disable : 4127) /* conditional expression is constant */
|
---|
47 | #pragma warning( disable : 4706) /* assignment within conditional function */
|
---|
48 | #endif
|
---|
49 | void qh_errexit(int exitcode, facetT *, ridgeT *);
|
---|
50 | void qh_exit(int exitcode);
|
---|
51 | void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
|
---|
52 | void qh_free(void *mem);
|
---|
53 | void *qh_malloc(size_t size);
|
---|
54 | #endif
|
---|
55 |
|
---|
56 | /*============ -global data structure ==============
|
---|
57 | see mem.h for definition
|
---|
58 | */
|
---|
59 |
|
---|
60 | qhmemT qhmem= {0,0,0,0,0,0,0,0,0,0,0,
|
---|
61 | 0,0,0,0,0,0,0,0,0,0,0,
|
---|
62 | 0,0,0,0,0,0,0}; /* remove "= {0}" if this causes a compiler error */
|
---|
63 |
|
---|
64 | #ifndef qh_NOmem
|
---|
65 |
|
---|
66 | /*============= internal functions ==============*/
|
---|
67 |
|
---|
68 | static int qh_intcompare(const void *i, const void *j);
|
---|
69 |
|
---|
70 | /*========== functions in alphabetical order ======== */
|
---|
71 |
|
---|
72 | /*-<a href="qh-mem.htm#TOC"
|
---|
73 | >-------------------------------</a><a name="intcompare">-</a>
|
---|
74 |
|
---|
75 | qh_intcompare( i, j )
|
---|
76 | used by qsort and bsearch to compare two integers
|
---|
77 | */
|
---|
78 | static int qh_intcompare(const void *i, const void *j) {
|
---|
79 | return(*((const int *)i) - *((const int *)j));
|
---|
80 | } /* intcompare */
|
---|
81 |
|
---|
82 |
|
---|
83 | /*-<a href="qh-mem.htm#TOC"
|
---|
84 | >--------------------------------</a><a name="memalloc">-</a>
|
---|
85 |
|
---|
86 | qh_memalloc( insize )
|
---|
87 | returns object of insize bytes
|
---|
88 | qhmem is the global memory structure
|
---|
89 |
|
---|
90 | returns:
|
---|
91 | pointer to allocated memory
|
---|
92 | errors if insufficient memory
|
---|
93 |
|
---|
94 | notes:
|
---|
95 | use explicit type conversion to avoid type warnings on some compilers
|
---|
96 | actual object may be larger than insize
|
---|
97 | use qh_memalloc_() for inline code for quick allocations
|
---|
98 | logs allocations if 'T5'
|
---|
99 |
|
---|
100 | design:
|
---|
101 | if size < qhmem.LASTsize
|
---|
102 | if qhmem.freelists[size] non-empty
|
---|
103 | return first object on freelist
|
---|
104 | else
|
---|
105 | round up request to size of qhmem.freelists[size]
|
---|
106 | allocate new allocation buffer if necessary
|
---|
107 | allocate object from allocation buffer
|
---|
108 | else
|
---|
109 | allocate object with qh_malloc() in user.c
|
---|
110 | */
|
---|
111 | void *qh_memalloc(int insize) {
|
---|
112 | void **freelistp, *newbuffer;
|
---|
113 | int idx, size, n;
|
---|
114 | int outsize, bufsize;
|
---|
115 | void *object;
|
---|
116 |
|
---|
117 | if (insize<0) {
|
---|
118 | qh_fprintf(qhmem.ferr, 6235, "qhull error (qh_memalloc): negative request size (%d). Did int overflow due to high-D?\n", insize); /* WARN64 */
|
---|
119 | qh_errexit(qhmem_ERRmem, NULL, NULL);
|
---|
120 | }
|
---|
121 | if (insize>=0 && insize <= qhmem.LASTsize) {
|
---|
122 | idx= qhmem.indextable[insize];
|
---|
123 | outsize= qhmem.sizetable[idx];
|
---|
124 | qhmem.totshort += outsize;
|
---|
125 | freelistp= qhmem.freelists+idx;
|
---|
126 | if ((object= *freelistp)) {
|
---|
127 | qhmem.cntquick++;
|
---|
128 | qhmem.totfree -= outsize;
|
---|
129 | *freelistp= *((void **)*freelistp); /* replace freelist with next object */
|
---|
130 | #ifdef qh_TRACEshort
|
---|
131 | n= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort;
|
---|
132 | if (qhmem.IStracing >= 5)
|
---|
133 | qh_fprintf(qhmem.ferr, 8141, "qh_mem %p n %8d alloc quick: %d bytes (tot %d cnt %d)\n", object, n, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort);
|
---|
134 | #endif
|
---|
135 | return(object);
|
---|
136 | }else {
|
---|
137 | qhmem.cntshort++;
|
---|
138 | if (outsize > qhmem .freesize) {
|
---|
139 | qhmem .totdropped += qhmem .freesize;
|
---|
140 | if (!qhmem.curbuffer)
|
---|
141 | bufsize= qhmem.BUFinit;
|
---|
142 | else
|
---|
143 | bufsize= qhmem.BUFsize;
|
---|
144 | if (!(newbuffer= qh_malloc((size_t)bufsize))) {
|
---|
145 | qh_fprintf(qhmem.ferr, 6080, "qhull error (qh_memalloc): insufficient memory to allocate short memory buffer (%d bytes)\n", bufsize);
|
---|
146 | qh_errexit(qhmem_ERRmem, NULL, NULL);
|
---|
147 | }
|
---|
148 | *((void **)newbuffer)= qhmem.curbuffer; /* prepend newbuffer to curbuffer
|
---|
149 | list */
|
---|
150 | qhmem.curbuffer= newbuffer;
|
---|
151 | size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
|
---|
152 | qhmem.freemem= (void *)((char *)newbuffer+size);
|
---|
153 | qhmem.freesize= bufsize - size;
|
---|
154 | qhmem.totbuffer += bufsize - size; /* easier to check */
|
---|
155 | /* Periodically test totbuffer. It matches at beginning and exit of every call */
|
---|
156 | n = qhmem.totshort + qhmem.totfree + qhmem.totdropped + qhmem.freesize - outsize;
|
---|
157 | if (qhmem.totbuffer != n) {
|
---|
158 | qh_fprintf(qhmem.ferr, 6212, "qh_memalloc internal error: short totbuffer %d != totshort+totfree... %d\n", qhmem.totbuffer, n);
|
---|
159 | qh_errexit(qhmem_ERRmem, NULL, NULL);
|
---|
160 | }
|
---|
161 | }
|
---|
162 | object= qhmem.freemem;
|
---|
163 | qhmem.freemem= (void *)((char *)qhmem.freemem + outsize);
|
---|
164 | qhmem.freesize -= outsize;
|
---|
165 | qhmem.totunused += outsize - insize;
|
---|
166 | #ifdef qh_TRACEshort
|
---|
167 | n= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort;
|
---|
168 | if (qhmem.IStracing >= 5)
|
---|
169 | qh_fprintf(qhmem.ferr, 8140, "qh_mem %p n %8d alloc short: %d bytes (tot %d cnt %d)\n", object, n, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort);
|
---|
170 | #endif
|
---|
171 | return object;
|
---|
172 | }
|
---|
173 | }else { /* long allocation */
|
---|
174 | if (!qhmem.indextable) {
|
---|
175 | qh_fprintf(qhmem.ferr, 6081, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n");
|
---|
176 | qh_errexit(qhmem_ERRqhull, NULL, NULL);
|
---|
177 | }
|
---|
178 | outsize= insize;
|
---|
179 | qhmem .cntlong++;
|
---|
180 | qhmem .totlong += outsize;
|
---|
181 | if (qhmem.maxlong < qhmem.totlong)
|
---|
182 | qhmem.maxlong= qhmem.totlong;
|
---|
183 | if (!(object= qh_malloc((size_t)outsize))) {
|
---|
184 | qh_fprintf(qhmem.ferr, 6082, "qhull error (qh_memalloc): insufficient memory to allocate %d bytes\n", outsize);
|
---|
185 | qh_errexit(qhmem_ERRmem, NULL, NULL);
|
---|
186 | }
|
---|
187 | if (qhmem.IStracing >= 5)
|
---|
188 | qh_fprintf(qhmem.ferr, 8057, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, outsize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
|
---|
189 | }
|
---|
190 | return(object);
|
---|
191 | } /* memalloc */
|
---|
192 |
|
---|
193 |
|
---|
194 | /*-<a href="qh-mem.htm#TOC"
|
---|
195 | >--------------------------------</a><a name="memfree">-</a>
|
---|
196 |
|
---|
197 | qh_memfree( object, insize )
|
---|
198 | free up an object of size bytes
|
---|
199 | size is insize from qh_memalloc
|
---|
200 |
|
---|
201 | notes:
|
---|
202 | object may be NULL
|
---|
203 | type checking warns if using (void **)object
|
---|
204 | use qh_memfree_() for quick free's of small objects
|
---|
205 |
|
---|
206 | design:
|
---|
207 | if size <= qhmem.LASTsize
|
---|
208 | append object to corresponding freelist
|
---|
209 | else
|
---|
210 | call qh_free(object)
|
---|
211 | */
|
---|
212 | void qh_memfree(void *object, int insize) {
|
---|
213 | void **freelistp;
|
---|
214 | int idx, outsize;
|
---|
215 |
|
---|
216 | if (!object)
|
---|
217 | return;
|
---|
218 | if (insize <= qhmem.LASTsize) {
|
---|
219 | qhmem .freeshort++;
|
---|
220 | idx= qhmem.indextable[insize];
|
---|
221 | outsize= qhmem.sizetable[idx];
|
---|
222 | qhmem .totfree += outsize;
|
---|
223 | qhmem .totshort -= outsize;
|
---|
224 | freelistp= qhmem.freelists + idx;
|
---|
225 | *((void **)object)= *freelistp;
|
---|
226 | *freelistp= object;
|
---|
227 | #ifdef qh_TRACEshort
|
---|
228 | idx= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort;
|
---|
229 | if (qhmem.IStracing >= 5)
|
---|
230 | qh_fprintf(qhmem.ferr, 8142, "qh_mem %p n %8d free short: %d bytes (tot %d cnt %d)\n", object, idx, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort);
|
---|
231 | #endif
|
---|
232 | }else {
|
---|
233 | qhmem .freelong++;
|
---|
234 | qhmem .totlong -= insize;
|
---|
235 | qh_free(object);
|
---|
236 | if (qhmem.IStracing >= 5)
|
---|
237 | qh_fprintf(qhmem.ferr, 8058, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
|
---|
238 | }
|
---|
239 | } /* memfree */
|
---|
240 |
|
---|
241 |
|
---|
242 | /*-<a href="qh-mem.htm#TOC"
|
---|
243 | >-------------------------------</a><a name="memfreeshort">-</a>
|
---|
244 |
|
---|
245 | qh_memfreeshort( curlong, totlong )
|
---|
246 | frees up all short and qhmem memory allocations
|
---|
247 |
|
---|
248 | returns:
|
---|
249 | number and size of current long allocations
|
---|
250 |
|
---|
251 | see:
|
---|
252 | qh_freeqhull(allMem)
|
---|
253 | qh_memtotal(curlong, totlong, curshort, totshort, maxlong, totbuffer);
|
---|
254 | */
|
---|
255 | void qh_memfreeshort(int *curlong, int *totlong) {
|
---|
256 | void *buffer, *nextbuffer;
|
---|
257 | FILE *ferr;
|
---|
258 |
|
---|
259 | *curlong= qhmem .cntlong - qhmem .freelong;
|
---|
260 | *totlong= qhmem .totlong;
|
---|
261 | for (buffer= qhmem.curbuffer; buffer; buffer= nextbuffer) {
|
---|
262 | nextbuffer= *((void **) buffer);
|
---|
263 | qh_free(buffer);
|
---|
264 | }
|
---|
265 | qhmem.curbuffer= NULL;
|
---|
266 | if (qhmem .LASTsize) {
|
---|
267 | qh_free(qhmem .indextable);
|
---|
268 | qh_free(qhmem .freelists);
|
---|
269 | qh_free(qhmem .sizetable);
|
---|
270 | }
|
---|
271 | ferr= qhmem.ferr;
|
---|
272 | memset((char *)&qhmem, 0, sizeof(qhmem)); /* every field is 0, FALSE, NULL */
|
---|
273 | qhmem.ferr= ferr;
|
---|
274 | } /* memfreeshort */
|
---|
275 |
|
---|
276 |
|
---|
277 | /*-<a href="qh-mem.htm#TOC"
|
---|
278 | >--------------------------------</a><a name="meminit">-</a>
|
---|
279 |
|
---|
280 | qh_meminit( ferr )
|
---|
281 | initialize qhmem and test sizeof( void*)
|
---|
282 | */
|
---|
283 | void qh_meminit(FILE *ferr) {
|
---|
284 |
|
---|
285 | memset((char *)&qhmem, 0, sizeof(qhmem)); /* every field is 0, FALSE, NULL */
|
---|
286 | qhmem.ferr= ferr;
|
---|
287 | if (sizeof(void*) < sizeof(int)) {
|
---|
288 | qh_fprintf(ferr, 6083, "qhull internal error (qh_meminit): sizeof(void*) %d < sizeof(int) %d. qset.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
|
---|
289 | qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */
|
---|
290 | }
|
---|
291 | if (sizeof(void*) > sizeof(ptr_intT)) {
|
---|
292 | qh_fprintf(ferr, 6084, "qhull internal error (qh_meminit): sizeof(void*) %d > sizeof(ptr_intT) %d. Change ptr_intT in mem.h to 'long long'\n", (int)sizeof(void*), (int)sizeof(ptr_intT));
|
---|
293 | qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */
|
---|
294 | }
|
---|
295 | } /* meminit */
|
---|
296 |
|
---|
297 | /*-<a href="qh-mem.htm#TOC"
|
---|
298 | >-------------------------------</a><a name="meminitbuffers">-</a>
|
---|
299 |
|
---|
300 | qh_meminitbuffers( tracelevel, alignment, numsizes, bufsize, bufinit )
|
---|
301 | initialize qhmem
|
---|
302 | if tracelevel >= 5, trace memory allocations
|
---|
303 | alignment= desired address alignment for memory allocations
|
---|
304 | numsizes= number of freelists
|
---|
305 | bufsize= size of additional memory buffers for short allocations
|
---|
306 | bufinit= size of initial memory buffer for short allocations
|
---|
307 | */
|
---|
308 | void qh_meminitbuffers(int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
|
---|
309 |
|
---|
310 | qhmem.IStracing= tracelevel;
|
---|
311 | qhmem.NUMsizes= numsizes;
|
---|
312 | qhmem.BUFsize= bufsize;
|
---|
313 | qhmem.BUFinit= bufinit;
|
---|
314 | qhmem.ALIGNmask= alignment-1;
|
---|
315 | if (qhmem.ALIGNmask & ~qhmem.ALIGNmask) {
|
---|
316 | qh_fprintf(qhmem.ferr, 6085, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment);
|
---|
317 | qh_errexit(qhmem_ERRqhull, NULL, NULL);
|
---|
318 | }
|
---|
319 | qhmem.sizetable= (int *) calloc((size_t)numsizes, sizeof(int));
|
---|
320 | qhmem.freelists= (void **) calloc((size_t)numsizes, sizeof(void *));
|
---|
321 | if (!qhmem.sizetable || !qhmem.freelists) {
|
---|
322 | qh_fprintf(qhmem.ferr, 6086, "qhull error (qh_meminit): insufficient memory\n");
|
---|
323 | qh_errexit(qhmem_ERRmem, NULL, NULL);
|
---|
324 | }
|
---|
325 | if (qhmem.IStracing >= 1)
|
---|
326 | qh_fprintf(qhmem.ferr, 8059, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
|
---|
327 | } /* meminitbuffers */
|
---|
328 |
|
---|
329 | /*-<a href="qh-mem.htm#TOC"
|
---|
330 | >-------------------------------</a><a name="memsetup">-</a>
|
---|
331 |
|
---|
332 | qh_memsetup()
|
---|
333 | set up memory after running memsize()
|
---|
334 | */
|
---|
335 | void qh_memsetup(void) {
|
---|
336 | int k,i;
|
---|
337 |
|
---|
338 | qsort(qhmem.sizetable, (size_t)qhmem.TABLEsize, sizeof(int), qh_intcompare);
|
---|
339 | qhmem.LASTsize= qhmem.sizetable[qhmem.TABLEsize-1];
|
---|
340 | if (qhmem .LASTsize >= qhmem .BUFsize || qhmem.LASTsize >= qhmem .BUFinit) {
|
---|
341 | qh_fprintf(qhmem.ferr, 6087, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n",
|
---|
342 | qhmem .LASTsize, qhmem .BUFsize, qhmem .BUFinit);
|
---|
343 | qh_errexit(qhmem_ERRmem, NULL, NULL);
|
---|
344 | }
|
---|
345 | if (!(qhmem.indextable= (int *)qh_malloc((qhmem.LASTsize+1) * sizeof(int)))) {
|
---|
346 | qh_fprintf(qhmem.ferr, 6088, "qhull error (qh_memsetup): insufficient memory\n");
|
---|
347 | qh_errexit(qhmem_ERRmem, NULL, NULL);
|
---|
348 | }
|
---|
349 | for (k=qhmem.LASTsize+1; k--; )
|
---|
350 | qhmem.indextable[k]= k;
|
---|
351 | i= 0;
|
---|
352 | for (k=0; k <= qhmem.LASTsize; k++) {
|
---|
353 | if (qhmem.indextable[k] <= qhmem.sizetable[i])
|
---|
354 | qhmem.indextable[k]= i;
|
---|
355 | else
|
---|
356 | qhmem.indextable[k]= ++i;
|
---|
357 | }
|
---|
358 | } /* memsetup */
|
---|
359 |
|
---|
360 | /*-<a href="qh-mem.htm#TOC"
|
---|
361 | >-------------------------------</a><a name="memsize">-</a>
|
---|
362 |
|
---|
363 | qh_memsize( size )
|
---|
364 | define a free list for this size
|
---|
365 | */
|
---|
366 | void qh_memsize(int size) {
|
---|
367 | int k;
|
---|
368 |
|
---|
369 | if (qhmem .LASTsize) {
|
---|
370 | qh_fprintf(qhmem.ferr, 6089, "qhull error (qh_memsize): called after qhmem_setup\n");
|
---|
371 | qh_errexit(qhmem_ERRqhull, NULL, NULL);
|
---|
372 | }
|
---|
373 | size= (size + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
|
---|
374 | for (k=qhmem.TABLEsize; k--; ) {
|
---|
375 | if (qhmem.sizetable[k] == size)
|
---|
376 | return;
|
---|
377 | }
|
---|
378 | if (qhmem.TABLEsize < qhmem.NUMsizes)
|
---|
379 | qhmem.sizetable[qhmem.TABLEsize++]= size;
|
---|
380 | else
|
---|
381 | qh_fprintf(qhmem.ferr, 7060, "qhull warning (memsize): free list table has room for only %d sizes\n", qhmem.NUMsizes);
|
---|
382 | } /* memsize */
|
---|
383 |
|
---|
384 |
|
---|
385 | /*-<a href="qh-mem.htm#TOC"
|
---|
386 | >-------------------------------</a><a name="memstatistics">-</a>
|
---|
387 |
|
---|
388 | qh_memstatistics( fp )
|
---|
389 | print out memory statistics
|
---|
390 |
|
---|
391 | Verifies that qhmem.totfree == sum of freelists
|
---|
392 | */
|
---|
393 | void qh_memstatistics(FILE *fp) {
|
---|
394 | int i, count, totfree= 0;
|
---|
395 | void *object;
|
---|
396 |
|
---|
397 | for (i=0; i < qhmem.TABLEsize; i++) {
|
---|
398 | count=0;
|
---|
399 | for (object= qhmem .freelists[i]; object; object= *((void **)object))
|
---|
400 | count++;
|
---|
401 | totfree += qhmem.sizetable[i] * count;
|
---|
402 | }
|
---|
403 | if (totfree != qhmem .totfree) {
|
---|
404 | qh_fprintf(qhmem.ferr, 6211, "qh_memstatistics internal error: totfree %d not equal to freelist total %d\n", qhmem.totfree, totfree);
|
---|
405 | qh_errexit(qhmem_ERRqhull, NULL, NULL);
|
---|
406 | }
|
---|
407 | qh_fprintf(fp, 9278, "\nmemory statistics:\n\
|
---|
408 | %7d quick allocations\n\
|
---|
409 | %7d short allocations\n\
|
---|
410 | %7d long allocations\n\
|
---|
411 | %7d short frees\n\
|
---|
412 | %7d long frees\n\
|
---|
413 | %7d bytes of short memory in use\n\
|
---|
414 | %7d bytes of short memory in freelists\n\
|
---|
415 | %7d bytes of dropped short memory\n\
|
---|
416 | %7d bytes of unused short memory (estimated)\n\
|
---|
417 | %7d bytes of long memory allocated (max, except for input)\n\
|
---|
418 | %7d bytes of long memory in use (in %d pieces)\n\
|
---|
419 | %7d bytes of short memory buffers (minus links)\n\
|
---|
420 | %7d bytes per short memory buffer (initially %d bytes)\n",
|
---|
421 | qhmem .cntquick, qhmem .cntshort, qhmem .cntlong,
|
---|
422 | qhmem .freeshort, qhmem .freelong,
|
---|
423 | qhmem .totshort, qhmem .totfree,
|
---|
424 | qhmem .totdropped + qhmem .freesize, qhmem .totunused,
|
---|
425 | qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong,
|
---|
426 | qhmem .totbuffer, qhmem .BUFsize, qhmem .BUFinit);
|
---|
427 | if (qhmem.cntlarger) {
|
---|
428 | qh_fprintf(fp, 9279, "%7d calls to qh_setlarger\n%7.2g average copy size\n",
|
---|
429 | qhmem.cntlarger, ((float)qhmem.totlarger)/(float)qhmem.cntlarger);
|
---|
430 | qh_fprintf(fp, 9280, " freelists(bytes->count):");
|
---|
431 | }
|
---|
432 | for (i=0; i < qhmem.TABLEsize; i++) {
|
---|
433 | count=0;
|
---|
434 | for (object= qhmem .freelists[i]; object; object= *((void **)object))
|
---|
435 | count++;
|
---|
436 | qh_fprintf(fp, 9281, " %d->%d", qhmem.sizetable[i], count);
|
---|
437 | }
|
---|
438 | qh_fprintf(fp, 9282, "\n\n");
|
---|
439 | } /* memstatistics */
|
---|
440 |
|
---|
441 |
|
---|
442 | /*-<a href="qh-mem.htm#TOC"
|
---|
443 | >-------------------------------</a><a name="NOmem">-</a>
|
---|
444 |
|
---|
445 | qh_NOmem
|
---|
446 | turn off quick-fit memory allocation
|
---|
447 |
|
---|
448 | notes:
|
---|
449 | uses qh_malloc() and qh_free() instead
|
---|
450 | */
|
---|
451 | #else /* qh_NOmem */
|
---|
452 |
|
---|
453 | void *qh_memalloc(int insize) {
|
---|
454 | void *object;
|
---|
455 |
|
---|
456 | if (!(object= qh_malloc((size_t)insize))) {
|
---|
457 | qh_fprintf(qhmem.ferr, 6090, "qhull error (qh_memalloc): insufficient memory\n");
|
---|
458 | qh_errexit(qhmem_ERRmem, NULL, NULL);
|
---|
459 | }
|
---|
460 | qhmem .cntlong++;
|
---|
461 | qhmem .totlong += insize;
|
---|
462 | if (qhmem.maxlong < qhmem.totlong)
|
---|
463 | qhmem.maxlong= qhmem.totlong;
|
---|
464 | if (qhmem.IStracing >= 5)
|
---|
465 | qh_fprintf(qhmem.ferr, 8060, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
|
---|
466 | return object;
|
---|
467 | }
|
---|
468 |
|
---|
469 | void qh_memfree(void *object, int insize) {
|
---|
470 |
|
---|
471 | if (!object)
|
---|
472 | return;
|
---|
473 | qh_free(object);
|
---|
474 | qhmem .freelong++;
|
---|
475 | qhmem .totlong -= insize;
|
---|
476 | if (qhmem.IStracing >= 5)
|
---|
477 | qh_fprintf(qhmem.ferr, 8061, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
|
---|
478 | }
|
---|
479 |
|
---|
480 | void qh_memfreeshort(int *curlong, int *totlong) {
|
---|
481 | *totlong= qhmem .totlong;
|
---|
482 | *curlong= qhmem .cntlong - qhmem .freelong;
|
---|
483 | memset((char *)&qhmem, 0, sizeof(qhmem)); /* every field is 0, FALSE, NULL */
|
---|
484 | }
|
---|
485 |
|
---|
486 | void qh_meminit(FILE *ferr) {
|
---|
487 |
|
---|
488 | memset((char *)&qhmem, 0, sizeof(qhmem)); /* every field is 0, FALSE, NULL */
|
---|
489 | qhmem.ferr= ferr;
|
---|
490 | if (sizeof(void*) < sizeof(int)) {
|
---|
491 | qh_fprintf(ferr, 6091, "qhull internal error (qh_meminit): sizeof(void*) %d < sizeof(int) %d. qset.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
|
---|
492 | qh_errexit(qhmem_ERRqhull, NULL, NULL);
|
---|
493 | }
|
---|
494 | }
|
---|
495 |
|
---|
496 | void qh_meminitbuffers(int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
|
---|
497 |
|
---|
498 | qhmem.IStracing= tracelevel;
|
---|
499 | }
|
---|
500 |
|
---|
501 | void qh_memsetup(void) {
|
---|
502 |
|
---|
503 | }
|
---|
504 |
|
---|
505 | void qh_memsize(int size) {
|
---|
506 |
|
---|
507 | }
|
---|
508 |
|
---|
509 | void qh_memstatistics(FILE *fp) {
|
---|
510 |
|
---|
511 | qh_fprintf(fp, 9409, "\nmemory statistics:\n\
|
---|
512 | %7d long allocations\n\
|
---|
513 | %7d long frees\n\
|
---|
514 | %7d bytes of long memory allocated (max, except for input)\n\
|
---|
515 | %7d bytes of long memory in use (in %d pieces)\n",
|
---|
516 | qhmem .cntlong,
|
---|
517 | qhmem .freelong,
|
---|
518 | qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong);
|
---|
519 | }
|
---|
520 |
|
---|
521 | #endif /* qh_NOmem */
|
---|
522 |
|
---|
523 | /*-<a href="qh-mem.htm#TOC"
|
---|
524 | >-------------------------------</a><a name="memtotlong">-</a>
|
---|
525 |
|
---|
526 | qh_memtotal( totlong, curlong, totshort, curshort, maxlong, totbuffer )
|
---|
527 | Return the total, allocated long and short memory
|
---|
528 |
|
---|
529 | returns:
|
---|
530 | Returns the total current bytes of long and short allocations
|
---|
531 | Returns the current count of long and short allocations
|
---|
532 | Returns the maximum long memory and total short buffer (minus one link per buffer)
|
---|
533 | Does not error (UsingLibQhull.cpp)
|
---|
534 | */
|
---|
535 | void qh_memtotal(int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer) {
|
---|
536 | *totlong= qhmem .totlong;
|
---|
537 | *curlong= qhmem .cntlong - qhmem .freelong;
|
---|
538 | *totshort= qhmem .totshort;
|
---|
539 | *curshort= qhmem .cntshort + qhmem .cntquick - qhmem .freeshort;
|
---|
540 | *maxlong= qhmem .maxlong;
|
---|
541 | *totbuffer= qhmem .totbuffer;
|
---|
542 | } /* memtotlong */
|
---|
543 |
|
---|