ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/QuickHull/mem.c
Revision: 3138
Committed: Tue May 29 22:51:00 2007 UTC (17 years, 11 months ago) by chuckv
Content type: text/plain
File size: 13474 byte(s)
Log Message:
Addded QuickHull to cvs.

File Contents

# Content
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(sizeof(facetT));
14 qh_memsize(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-2003 The Geometry Center
33 */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include "config.h"
39 #include "QuickHull/mem.h"
40
41 #ifndef qhDEFqhull
42 typedef struct ridgeT ridgeT;
43 typedef struct facetT facetT;
44 void qh_errexit(int exitcode, facetT *, ridgeT *);
45 #endif
46
47 /*============ -global data structure ==============
48 see mem.h for definition
49 */
50
51 qhmemT qhmem= {0}; /* remove "= {0}" if this causes a compiler error */
52
53 #ifndef qh_NOmem
54
55 /*============= internal functions ==============*/
56
57 static int qh_intcompare(const void *i, const void *j);
58
59 /*========== functions in alphabetical order ======== */
60
61 /*-<a href="qh-mem.htm#TOC"
62 >-------------------------------</a><a name="intcompare">-</a>
63
64 qh_intcompare( i, j )
65 used by qsort and bsearch to compare two integers
66 */
67 static int qh_intcompare(const void *i, const void *j) {
68 return(*((int *)i) - *((int *)j));
69 } /* intcompare */
70
71
72 /*-<a href="qh-mem.htm#TOC"
73 >--------------------------------</a><a name="memalloc">-</a>
74
75 qh_memalloc( insize )
76 returns object of insize bytes
77 qhmem is the global memory structure
78
79 returns:
80 pointer to allocated memory
81 errors if insufficient memory
82
83 notes:
84 please use explicit type conversion to avoid type warnings on some compilers
85 actual object may be larger than insize
86 please use qh_memalloc_() for inline code for quick allocations
87 logs allocations if 'T5'
88
89 design:
90 if size < qhmem.LASTsize
91 if qhmem.freelists[size] non-empty
92 return first object on freelist
93 else
94 round up request to size of qhmem.freelists[size]
95 allocate new allocation buffer if necessary
96 allocate object from allocation buffer
97 else
98 allocate object with malloc()
99 */
100 void *qh_memalloc(int insize) {
101 void **freelistp, *newbuffer;
102 int index, size;
103 int outsize, bufsize;
104 void *object;
105
106 if ((unsigned) insize <= (unsigned) qhmem.LASTsize) {
107 index= qhmem.indextable[insize];
108 freelistp= qhmem.freelists+index;
109 if ((object= *freelistp)) {
110 qhmem.cntquick++;
111 *freelistp= *((void **)*freelistp); /* replace freelist with next object */
112 return (object);
113 }else {
114 outsize= qhmem.sizetable[index];
115 qhmem.cntshort++;
116 if (outsize > qhmem .freesize) {
117 if (!qhmem.curbuffer)
118 bufsize= qhmem.BUFinit;
119 else
120 bufsize= qhmem.BUFsize;
121 qhmem.totshort += bufsize;
122 if (!(newbuffer= malloc(bufsize))) {
123 fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
124 qh_errexit(qhmem_ERRmem, NULL, NULL);
125 }
126 *((void **)newbuffer)= qhmem.curbuffer; /* prepend newbuffer to curbuffer
127 list */
128 qhmem.curbuffer= newbuffer;
129 size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
130 qhmem.freemem= (void *)((char *)newbuffer+size);
131 qhmem.freesize= bufsize - size;
132 }
133 object= qhmem.freemem;
134 qhmem.freemem= (void *)((char *)qhmem.freemem + outsize);
135 qhmem.freesize -= outsize;
136 return object;
137 }
138 }else { /* long allocation */
139 if (!qhmem.indextable) {
140 fprintf (qhmem.ferr, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n");
141 qh_errexit(qhmem_ERRqhull, NULL, NULL);
142 }
143 outsize= insize;
144 qhmem .cntlong++;
145 qhmem .curlong++;
146 qhmem .totlong += outsize;
147 if (qhmem.maxlong < qhmem.totlong)
148 qhmem.maxlong= qhmem.totlong;
149 if (!(object= malloc(outsize))) {
150 fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
151 qh_errexit(qhmem_ERRmem, NULL, NULL);
152 }
153 if (qhmem.IStracing >= 5)
154 fprintf (qhmem.ferr, "qh_memalloc long: %d bytes at %p\n", outsize, object);
155 }
156 return (object);
157 } /* memalloc */
158
159
160 /*-<a href="qh-mem.htm#TOC"
161 >--------------------------------</a><a name="memfree">-</a>
162
163 qh_memfree( object, size )
164 free up an object of size bytes
165 size is insize from qh_memalloc
166
167 notes:
168 object may be NULL
169 type checking warns if using (void **)object
170 please use qh_memfree_() for quick free's of small objects
171
172 design:
173 if size <= qhmem.LASTsize
174 append object to corresponding freelist
175 else
176 call free(object)
177 */
178 void qh_memfree(void *object, int size) {
179 void **freelistp;
180
181 if (!object)
182 return;
183 if (size <= qhmem.LASTsize) {
184 qhmem .freeshort++;
185 freelistp= qhmem.freelists + qhmem.indextable[size];
186 *((void **)object)= *freelistp;
187 *freelistp= object;
188 }else {
189 qhmem .freelong++;
190 qhmem .totlong -= size;
191 free (object);
192 if (qhmem.IStracing >= 5)
193 fprintf (qhmem.ferr, "qh_memfree long: %d bytes at %p\n", size, object);
194 }
195 } /* memfree */
196
197
198 /*-<a href="qh-mem.htm#TOC"
199 >-------------------------------</a><a name="memfreeshort">-</a>
200
201 qh_memfreeshort( curlong, totlong )
202 frees up all short and qhmem memory allocations
203
204 returns:
205 number and size of current long allocations
206 */
207 void qh_memfreeshort (int *curlong, int *totlong) {
208 void *buffer, *nextbuffer;
209 FILE *ferr;
210
211 *curlong= qhmem .cntlong - qhmem .freelong;
212 *totlong= qhmem .totlong;
213 for(buffer= qhmem.curbuffer; buffer; buffer= nextbuffer) {
214 nextbuffer= *((void **) buffer);
215 free(buffer);
216 }
217 qhmem.curbuffer= NULL;
218 if (qhmem .LASTsize) {
219 free (qhmem .indextable);
220 free (qhmem .freelists);
221 free (qhmem .sizetable);
222 }
223 ferr= qhmem.ferr;
224 memset((char *)&qhmem, 0, sizeof qhmem); /* every field is 0, FALSE, NULL */
225 qhmem.ferr= ferr;
226 } /* memfreeshort */
227
228
229 /*-<a href="qh-mem.htm#TOC"
230 >--------------------------------</a><a name="meminit">-</a>
231
232 qh_meminit( ferr )
233 initialize qhmem and test sizeof( void*)
234 */
235 void qh_meminit (FILE *ferr) {
236
237 memset((char *)&qhmem, 0, sizeof qhmem); /* every field is 0, FALSE, NULL */
238 qhmem.ferr= ferr;
239 if (sizeof(void*) < sizeof(int)) {
240 fprintf (ferr, "qhull internal error (qh_meminit): sizeof(void*) < sizeof(int). qset.c will not work\n");
241 exit (1); /* can not use qh_errexit() */
242 }
243 } /* meminit */
244
245 /*-<a href="qh-mem.htm#TOC"
246 >-------------------------------</a><a name="meminitbuffers">-</a>
247
248 qh_meminitbuffers( tracelevel, alignment, numsizes, bufsize, bufinit )
249 initialize qhmem
250 if tracelevel >= 5, trace memory allocations
251 alignment= desired address alignment for memory allocations
252 numsizes= number of freelists
253 bufsize= size of additional memory buffers for short allocations
254 bufinit= size of initial memory buffer for short allocations
255 */
256 void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
257
258 qhmem.IStracing= tracelevel;
259 qhmem.NUMsizes= numsizes;
260 qhmem.BUFsize= bufsize;
261 qhmem.BUFinit= bufinit;
262 qhmem.ALIGNmask= alignment-1;
263 if (qhmem.ALIGNmask & ~qhmem.ALIGNmask) {
264 fprintf (qhmem.ferr, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment);
265 qh_errexit (qhmem_ERRqhull, NULL, NULL);
266 }
267 qhmem.sizetable= (int *) calloc (numsizes, sizeof(int));
268 qhmem.freelists= (void **) calloc (numsizes, sizeof(void *));
269 if (!qhmem.sizetable || !qhmem.freelists) {
270 fprintf(qhmem.ferr, "qhull error (qh_meminit): insufficient memory\n");
271 qh_errexit (qhmem_ERRmem, NULL, NULL);
272 }
273 if (qhmem.IStracing >= 1)
274 fprintf (qhmem.ferr, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
275 } /* meminitbuffers */
276
277 /*-<a href="qh-mem.htm#TOC"
278 >-------------------------------</a><a name="memsetup">-</a>
279
280 qh_memsetup()
281 set up memory after running memsize()
282 */
283 void qh_memsetup (void) {
284 int k,i;
285
286 qsort(qhmem.sizetable, qhmem.TABLEsize, sizeof(int), qh_intcompare);
287 qhmem.LASTsize= qhmem.sizetable[qhmem.TABLEsize-1];
288 if (qhmem .LASTsize >= qhmem .BUFsize || qhmem.LASTsize >= qhmem .BUFinit) {
289 fprintf (qhmem.ferr, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n",
290 qhmem .LASTsize, qhmem .BUFsize, qhmem .BUFinit);
291 qh_errexit(qhmem_ERRmem, NULL, NULL);
292 }
293 if (!(qhmem.indextable= (int *)malloc((qhmem.LASTsize+1) * sizeof(int)))) {
294 fprintf(qhmem.ferr, "qhull error (qh_memsetup): insufficient memory\n");
295 qh_errexit(qhmem_ERRmem, NULL, NULL);
296 }
297 for(k=qhmem.LASTsize+1; k--; )
298 qhmem.indextable[k]= k;
299 i= 0;
300 for(k= 0; k <= qhmem.LASTsize; k++) {
301 if (qhmem.indextable[k] <= qhmem.sizetable[i])
302 qhmem.indextable[k]= i;
303 else
304 qhmem.indextable[k]= ++i;
305 }
306 } /* memsetup */
307
308 /*-<a href="qh-mem.htm#TOC"
309 >-------------------------------</a><a name="memsize">-</a>
310
311 qh_memsize( size )
312 define a free list for this size
313 */
314 void qh_memsize(int size) {
315 int k;
316
317 if (qhmem .LASTsize) {
318 fprintf (qhmem .ferr, "qhull error (qh_memsize): called after qhmem_setup\n");
319 qh_errexit (qhmem_ERRqhull, NULL, NULL);
320 }
321 size= (size + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
322 for(k= qhmem.TABLEsize; k--; ) {
323 if (qhmem.sizetable[k] == size)
324 return;
325 }
326 if (qhmem.TABLEsize < qhmem.NUMsizes)
327 qhmem.sizetable[qhmem.TABLEsize++]= size;
328 else
329 fprintf(qhmem.ferr, "qhull warning (memsize): free list table has room for only %d sizes\n", qhmem.NUMsizes);
330 } /* memsize */
331
332
333 /*-<a href="qh-mem.htm#TOC"
334 >-------------------------------</a><a name="memstatistics">-</a>
335
336 qh_memstatistics( fp )
337 print out memory statistics
338
339 notes:
340 does not account for wasted memory at the end of each block
341 */
342 void qh_memstatistics (FILE *fp) {
343 int i, count, totfree= 0;
344 void *object;
345
346 for (i=0; i < qhmem.TABLEsize; i++) {
347 count=0;
348 for (object= qhmem .freelists[i]; object; object= *((void **)object))
349 count++;
350 totfree += qhmem.sizetable[i] * count;
351 }
352 fprintf (fp, "\nmemory statistics:\n\
353 %7d quick allocations\n\
354 %7d short allocations\n\
355 %7d long allocations\n\
356 %7d short frees\n\
357 %7d long frees\n\
358 %7d bytes of short memory in use\n\
359 %7d bytes of short memory in freelists\n\
360 %7d bytes of long memory allocated (except for input)\n\
361 %7d bytes of long memory in use (in %d pieces)\n\
362 %7d bytes per memory buffer (initially %d bytes)\n",
363 qhmem .cntquick, qhmem.cntshort, qhmem.cntlong,
364 qhmem .freeshort, qhmem.freelong,
365 qhmem .totshort - qhmem .freesize - totfree,
366 totfree,
367 qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong,
368 qhmem .BUFsize, qhmem .BUFinit);
369 if (qhmem.cntlarger) {
370 fprintf (fp, "%7d calls to qh_setlarger\n%7.2g average copy size\n",
371 qhmem.cntlarger, ((float) qhmem.totlarger)/ qhmem.cntlarger);
372 fprintf (fp, " freelists (bytes->count):");
373 }
374 for (i=0; i < qhmem.TABLEsize; i++) {
375 count=0;
376 for (object= qhmem .freelists[i]; object; object= *((void **)object))
377 count++;
378 fprintf (fp, " %d->%d", qhmem.sizetable[i], count);
379 }
380 fprintf (fp, "\n\n");
381 } /* memstatistics */
382
383
384 /*-<a href="qh-mem.htm#TOC"
385 >-------------------------------</a><a name="NOmem">-</a>
386
387 qh_NOmem
388 turn off quick-fit memory allocation
389
390 notes:
391 uses malloc() and free() instead
392 */
393 #else /* qh_NOmem */
394
395 void *qh_memalloc(int insize) {
396 void *object;
397
398 if (!(object= malloc(insize))) {
399 fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
400 qh_errexit(qhmem_ERRmem, NULL, NULL);
401 }
402 if (qhmem.IStracing >= 5)
403 fprintf (qhmem.ferr, "qh_memalloc long: %d bytes at %p\n", insize, object);
404 return object;
405 }
406
407 void qh_memfree(void *object, int size) {
408
409 if (!object)
410 return;
411 free (object);
412 if (qhmem.IStracing >= 5)
413 fprintf (qhmem.ferr, "qh_memfree long: %d bytes at %p\n", size, object);
414 }
415
416 void qh_memfreeshort (int *curlong, int *totlong) {
417
418 memset((char *)&qhmem, 0, sizeof qhmem); /* every field is 0, FALSE, NULL */
419 *curlong= 0;
420 *totlong= 0;
421 }
422
423 void qh_meminit (FILE *ferr) {
424
425 memset((char *)&qhmem, 0, sizeof qhmem); /* every field is 0, FALSE, NULL */
426 qhmem.ferr= ferr;
427 if (sizeof(void*) < sizeof(int)) {
428 fprintf (ferr, "qhull internal error (qh_meminit): sizeof(void*) < sizeof(int). qset.c will not work\n");
429 qh_errexit (qhmem_ERRqhull, NULL, NULL);
430 }
431 }
432
433 void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
434
435 qhmem.IStracing= tracelevel;
436
437 }
438
439 void qh_memsetup (void) {
440
441 }
442
443 void qh_memsize(int size) {
444
445 }
446
447 void qh_memstatistics (FILE *fp) {
448
449 }
450
451 #endif /* qh_NOmem */