[10207] | 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 |
|
---|