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-2015 The Geometry Center.
15    $Id: //main/2015/qhull/src/libqhull/mem.h#2 $$Change: 2062 $
16    $DateTime: 2016/01/17 13:13:18 $$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 (defined(__MINGW64__)) && defined(_WIN64)
82 typedef long long ptr_intT;
83 #elif (_MSC_VER) && defined(_WIN64)
84 typedef long long ptr_intT;
85 #else
86 typedef long ptr_intT;
87 #endif
88 
89 /*-<a                             href="qh-mem.htm#TOC"
90   >--------------------------------</a><a name="qhmemT">-</a>
91 
92   qhmemT
93     global memory structure for mem.c
94 
95  notes:
96    users should ignore qhmem except for writing extensions
97    qhmem is allocated in mem.c
98 
99    qhmem could be swapable like qh and qhstat, but then
100    multiple qh's and qhmem's would need to keep in synch.
101    A swapable qhmem would also waste memory buffers.  As long
102    as memory operations are atomic, there is no problem with
103    multiple qh structures being active at the same time.
104    If you need separate address spaces, you can swap the
105    contents of qhmem.
106 */
107 typedef struct qhmemT qhmemT;
108 extern qhmemT qhmem;
109 
110 #ifndef DEFsetT
111 #define DEFsetT 1
112 typedef struct setT setT;          /* defined in qset.h */
113 #endif
114 
115 /* Update qhmem in mem.c if add or remove fields */
116 struct qhmemT {               /* global memory management variables */
117   int      BUFsize;           /* size of memory allocation buffer */
118   int      BUFinit;           /* initial size of memory allocation buffer */
119   int      TABLEsize;         /* actual number of sizes in free list table */
120   int      NUMsizes;          /* maximum number of sizes in free list table */
121   int      LASTsize;          /* last size in free list table */
122   int      ALIGNmask;         /* worst-case alignment, must be 2^n-1 */
123   void   **freelists;          /* free list table, linked by offset 0 */
124   int     *sizetable;         /* size of each freelist */
125   int     *indextable;        /* size->index table */
126   void    *curbuffer;         /* current buffer, linked by offset 0 */
127   void    *freemem;           /*   free memory in curbuffer */
128   int      freesize;          /*   size of freemem in bytes */
129   setT    *tempstack;         /* stack of temporary memory, managed by users */
130   FILE    *ferr;              /* file for reporting errors when 'qh' may be undefined */
131   int      IStracing;         /* =5 if tracing memory allocations */
132   int      cntquick;          /* count of quick allocations */
133                               /* Note: removing statistics doesn't effect speed */
134   int      cntshort;          /* count of short allocations */
135   int      cntlong;           /* count of long allocations */
136   int      freeshort;         /* count of short memfrees */
137   int      freelong;          /* count of long memfrees */
138   int      totbuffer;         /* total short memory buffers minus buffer links */
139   int      totdropped;        /* total dropped memory at end of short memory buffers (e.g., freesize) */
140   int      totfree;           /* total size of free, short memory on freelists */
141   int      totlong;           /* total size of long memory in use */
142   int      maxlong;           /*   maximum totlong */
143   int      totshort;          /* total size of short memory in use */
144   int      totunused;         /* total unused short memory (estimated, short size - request size of first allocations) */
145   int      cntlarger;         /* count of setlarger's */
146   int      totlarger;         /* total copied by setlarger */
147 };
148 
149 
150 /*==================== -macros ====================*/
151 
152 /*-<a                             href="qh-mem.htm#TOC"
153   >--------------------------------</a><a name="memalloc_">-</a>
154 
155   qh_memalloc_(insize, freelistp, object, type)
156     returns object of size bytes
157         assumes size<=qhmem.LASTsize and void **freelistp is a temp
158 */
159 
160 #if defined qh_NOmem
161 #define qh_memalloc_(insize, freelistp, object, type) {\
162   object= (type*)qh_memalloc(insize); }
163 #elif defined qh_TRACEshort
164 #define qh_memalloc_(insize, freelistp, object, type) {\
165     freelistp= NULL; /* Avoid warnings */ \
166     object= (type*)qh_memalloc(insize); }
167 #else /* !qh_NOmem */
168 
169 #define qh_memalloc_(insize, freelistp, object, type) {\
170   freelistp= qhmem.freelists + qhmem.indextable[insize];\
171   if ((object= (type*)*freelistp)) {\
172     qhmem.totshort += qhmem.sizetable[qhmem.indextable[insize]]; \
173     qhmem.totfree -= qhmem.sizetable[qhmem.indextable[insize]]; \
174     qhmem.cntquick++;  \
175     *freelistp= *((void **)*freelistp);\
176   }else object= (type*)qh_memalloc(insize);}
177 #endif
178 
179 /*-<a                             href="qh-mem.htm#TOC"
180   >--------------------------------</a><a name="memfree_">-</a>
181 
182   qh_memfree_(object, insize, freelistp)
183     free up an object
184 
185   notes:
186     object may be NULL
187     assumes size<=qhmem.LASTsize and void **freelistp is a temp
188 */
189 #if defined qh_NOmem
190 #define qh_memfree_(object, insize, freelistp) {\
191   qh_memfree(object, insize); }
192 #elif defined qh_TRACEshort
193 #define qh_memfree_(object, insize, freelistp) {\
194     freelistp= NULL; /* Avoid warnings */ \
195     qh_memfree(object, insize); }
196 #else /* !qh_NOmem */
197 
198 #define qh_memfree_(object, insize, freelistp) {\
199   if (object) { \
200     qhmem.freeshort++;\
201     freelistp= qhmem.freelists + qhmem.indextable[insize];\
202     qhmem.totshort -= qhmem.sizetable[qhmem.indextable[insize]]; \
203     qhmem.totfree += qhmem.sizetable[qhmem.indextable[insize]]; \
204     *((void **)object)= *freelistp;\
205     *freelistp= object;}}
206 #endif
207 
208 /*=============== prototypes in alphabetical order ============*/
209 
210 void *qh_memalloc(int insize);
211 void qh_memcheck(void);
212 void qh_memfree(void *object, int insize);
213 void qh_memfreeshort(int *curlong, int *totlong);
214 void qh_meminit(FILE *ferr);
215 void qh_meminitbuffers(int tracelevel, int alignment, int numsizes,
216                         int bufsize, int bufinit);
217 void qh_memsetup(void);
218 void qh_memsize(int size);
219 void qh_memstatistics(FILE *fp);
220 void qh_memtotal(int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer);
221 
222 #endif /* qhDEFmem */
223