1 /*<html><pre>  -<a                             href="qh-mem.htm"
2   >-------------------------------</a><a name="TOP">-</a>
3 
4    mem.h
5      prototypes for memory management functions
6 
7    see qh-mem.htm, mem.c and qset.h
8 
9    for error handling, writes message and calls
10      qh_errexit(qhmem_ERRmem, NULL, NULL) if insufficient memory
11        and
12      qh_errexit(qhmem_ERRqhull, NULL, NULL) otherwise
13 
14    Copyright (c) 1993-2012 The Geometry Center.
15    $Id: //main/2011/qhull/src/libqhull/mem.h#4 $$Change: 1464 $
16    $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
17 */
18 
19 #ifndef qhDEFmem
20 #define qhDEFmem 1
21 
22 #include <stdio.h>
23 
24 /*-<a                             href="qh-mem.htm#TOC"
25   >-------------------------------</a><a name="NOmem">-</a>
26 
27   qh_NOmem
28     turn off quick-fit memory allocation
29 
30   notes:
31     mem.c implements Quickfit memory allocation for about 20% time
32     savings.  If it fails on your machine, try to locate the
33     problem, and send the answer to qhull@qhull.org.  If this can
34     not be done, define qh_NOmem to use malloc/free instead.
35 
36    #define qh_NOmem
37 */
38 
39 /*-<a                             href="qh-mem.htm#TOC"
40 >-------------------------------</a><a name="TRACEshort">-</a>
41 
42 qh_TRACEshort
43 Trace short and quick memory allocations at T5
44 
45 */
46 #define qh_TRACEshort
47 
48 /*-------------------------------------------
49     to avoid bus errors, memory allocation must consider alignment requirements.
50     malloc() automatically takes care of alignment.   Since mem.c manages
51     its own memory, we need to explicitly specify alignment in
52     qh_meminitbuffers().
53 
54     A safe choice is sizeof(double).  sizeof(float) may be used if doubles
55     do not occur in data structures and pointers are the same size.  Be careful
56     of machines (e.g., DEC Alpha) with large pointers.  If gcc is available,
57     use __alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)).
58 
59    see <a href="user.h#MEMalign">qh_MEMalign</a> in user.h for qhull's alignment
60 */
61 
62 #define qhmem_ERRmem 4    /* matches qh_ERRmem in libqhull.h */
63 #define qhmem_ERRqhull 5  /* matches qh_ERRqhull in libqhull.h */
64 
65 /*-<a                             href="qh-mem.htm#TOC"
66   >--------------------------------</a><a name="ptr_intT">-</a>
67 
68   ptr_intT
69     for casting a void * to an integer-type that holds a pointer
70     Used for integer expressions (e.g., computing qh_gethash() in poly.c)
71 
72   notes:
73     WARN64 -- these notes indicate 64-bit issues
74     On 64-bit machines, a pointer may be larger than an 'int'.
75     qh_meminit()/mem.c checks that 'ptr_intT' holds a 'void*'
76     ptr_intT is typically a signed value, but not necessarily so
77     size_t is typically unsigned, but should match the parameter type
78     Qhull uses int instead of size_t except for system calls such as malloc, qsort, qh_malloc, etc.
79     This matches Qt convention and is easier to work with.
80 */
81 #if _MSC_VER && defined(_WIN64)
82 typedef long long ptr_intT;
83 #else
84 typedef long ptr_intT;
85 #endif
86 
87 /*-<a                             href="qh-mem.htm#TOC"
88   >--------------------------------</a><a name="qhmemT">-</a>
89 
90   qhmemT
91     global memory structure for mem.c
92 
93  notes:
94    users should ignore qhmem except for writing extensions
95    qhmem is allocated in mem.c
96 
97    qhmem could be swapable like qh and qhstat, but then
98    multiple qh's and qhmem's would need to keep in sync.
99    A swapable qhmem would also waste memory buffers.  As long
100    as memory operations are atomic, there is no problem with
101    multiple qh structures being active at the same time.
102    If you need separate address spaces, you can swap the
103    contents of qhmem.
104 */
105 typedef struct qhmemT qhmemT;
106 extern qhmemT qhmem;
107 
108 #ifndef DEFsetT
109 #define DEFsetT 1
110 typedef struct setT setT;          /* defined in qset.h */
111 #endif
112 
113 /* Update qhmem in mem.c if add or remove fields */
114 struct qhmemT {               /* global memory management variables */
115   int      BUFsize;           /* size of memory allocation buffer */
116   int      BUFinit;           /* initial size of memory allocation buffer */
117   int      TABLEsize;         /* actual number of sizes in free list table */
118   int      NUMsizes;          /* maximum number of sizes in free list table */
119   int      LASTsize;          /* last size in free list table */
120   int      ALIGNmask;         /* worst-case alignment, must be 2^n-1 */
121   void   **freelists;          /* free list table, linked by offset 0 */
122   int     *sizetable;         /* size of each freelist */
123   int     *indextable;        /* size->index table */
124   void    *curbuffer;         /* current buffer, linked by offset 0 */
125   void    *freemem;           /*   free memory in curbuffer */
126   int      freesize;          /*   size of freemem in bytes */
127   setT    *tempstack;         /* stack of temporary memory, managed by users */
128   FILE    *ferr;              /* file for reporting errors, only user is qh_fprintf() */
129   int      IStracing;         /* =5 if tracing memory allocations */
130   int      cntquick;          /* count of quick allocations */
131                               /* Note: removing statistics doesn't effect speed */
132   int      cntshort;          /* count of short allocations */
133   int      cntlong;           /* count of long allocations */
134   int      freeshort;         /* count of short memfrees */
135   int      freelong;          /* count of long memfrees */
136   int      totbuffer;         /* total short memory buffers minus buffer links */
137   int      totdropped;        /* total dropped memory at end of short memory buffers (e.g., freesize) */
138   int      totfree;           /* total size of free, short memory on freelists */
139   int      totlong;           /* total size of long memory in use */
140   int      maxlong;           /*   maximum totlong */
141   int      totshort;          /* total size of short memory in use */
142   int      totunused;         /* total unused short memory (estimated, short size - request size of first allocations) */
143   int      cntlarger;         /* count of setlarger's */
144   int      totlarger;         /* total copied by setlarger */
145 };
146 
147 
148 /*==================== -macros ====================*/
149 
150 /*-<a                             href="qh-mem.htm#TOC"
151   >--------------------------------</a><a name="memalloc_">-</a>
152 
153   qh_memalloc_(insize, object, type)
154     returns object of size bytes
155         assumes size<=qhmem.LASTsize and void **freelistp is a temp
156 */
157 
158 #if defined qh_NOmem
159 #define qh_memalloc_(insize, freelistp, object, type) {\
160   object= (type*)qh_memalloc(insize); }
161 #elif defined qh_TRACEshort
162 #define qh_memalloc_(insize, freelistp, object, type) {\
163     freelistp= NULL; /* Avoid warnings */ \
164     object= (type*)qh_memalloc(insize); }
165 #else /* !qh_NOmem */
166 
167 #define qh_memalloc_(insize, freelistp, object, type) {\
168   freelistp= qhmem.freelists + qhmem.indextable[insize];\
169   if ((object= (type*)*freelistp)) {\
170     qhmem.totshort += qhmem.sizetable[qhmem.indextable[insize]]; \
171     qhmem.totfree -= qhmem.sizetable[qhmem.indextable[insize]]; \
172     qhmem.cntquick++;  \
173     *freelistp= *((void **)*freelistp);\
174   }else object= (type*)qh_memalloc(insize);}
175 #endif
176 
177 /*-<a                             href="qh-mem.htm#TOC"
178   >--------------------------------</a><a name="memfree_">-</a>
179 
180   qh_memfree_(object, insize)
181     free up an object
182 
183   notes:
184     object may be NULL
185     assumes size<=qhmem.LASTsize and void **freelistp is a temp
186 */
187 #if defined qh_NOmem
188 #define qh_memfree_(object, insize, freelistp) {\
189   qh_memfree(object, insize); }
190 #elif defined qh_TRACEshort
191 #define qh_memfree_(object, insize, freelistp) {\
192     freelistp= NULL; /* Avoid warnings */ \
193     qh_memfree(object, insize); }
194 #else /* !qh_NOmem */
195 
196 #define qh_memfree_(object, insize, freelistp) {\
197   if (object) { \
198     qhmem .freeshort++;\
199     freelistp= qhmem.freelists + qhmem.indextable[insize];\
200     qhmem.totshort -= qhmem.sizetable[qhmem.indextable[insize]]; \
201     qhmem.totfree += qhmem.sizetable[qhmem.indextable[insize]]; \
202     *((void **)object)= *freelistp;\
203     *freelistp= object;}}
204 #endif
205 
206 /*=============== prototypes in alphabetical order ============*/
207 
208 void *qh_memalloc(int insize);
209 void qh_memfree(void *object, int insize);
210 void qh_memfreeshort(int *curlong, int *totlong);
211 void qh_meminit(FILE *ferr);
212 void qh_meminitbuffers(int tracelevel, int alignment, int numsizes,
213                         int bufsize, int bufinit);
214 void qh_memsetup(void);
215 void qh_memsize(int size);
216 void qh_memstatistics(FILE *fp);
217 void qh_memtotal(int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer);
218 
219 #endif /* qhDEFmem */
220