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