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-2003, The Geometry Center |
15 |
*/ |
16 |
|
17 |
#ifndef qhDEFmem |
18 |
#define qhDEFmem |
19 |
|
20 |
/*-<a href="qh-mem.htm#TOC" |
21 |
>-------------------------------</a><a name="NOmem">-</a> |
22 |
|
23 |
qh_NOmem |
24 |
turn off quick-fit memory allocation |
25 |
|
26 |
notes: |
27 |
mem.c implements Quickfit memory allocation for about 20% time |
28 |
savings. If it fails on your machine, try to locate the |
29 |
problem, and send the answer to qhull@qhull.org. If this can |
30 |
not be done, define qh_NOmem to use malloc/free instead. |
31 |
|
32 |
#define qh_NOmem |
33 |
*/ |
34 |
|
35 |
/*------------------------------------------- |
36 |
to avoid bus errors, memory allocation must consider alignment requirements. |
37 |
malloc() automatically takes care of alignment. Since mem.c manages |
38 |
its own memory, we need to explicitly specify alignment in |
39 |
qh_meminitbuffers(). |
40 |
|
41 |
A safe choice is sizeof(double). sizeof(float) may be used if doubles |
42 |
do not occur in data structures and pointers are the same size. Be careful |
43 |
of machines (e.g., DEC Alpha) with large pointers. If gcc is available, use |
44 |
__alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)). |
45 |
|
46 |
see <a href="user.h#MEMalign">qh_MEMalign</a> in user.h for qhull's alignment |
47 |
*/ |
48 |
|
49 |
/* matches qh_ERRmem in qhull.h */ |
50 |
#define qhmem_ERRmem 4 |
51 |
/* matches qh_ERRqhull in qhull.h */ |
52 |
#define qhmem_ERRqhull 5 |
53 |
|
54 |
/*-<a href="qh-mem.htm#TOC" |
55 |
>--------------------------------</a><a name="ptr_intT">-</a> |
56 |
|
57 |
ptr_intT |
58 |
for casting a void* to an integer-type |
59 |
|
60 |
notes: |
61 |
On 64-bit machines, a pointer may be larger than an 'int'. |
62 |
qh_meminit() checks that 'long' holds a 'void*' |
63 |
*/ |
64 |
typedef unsigned long ptr_intT; |
65 |
|
66 |
/*-<a href="qh-mem.htm#TOC" |
67 |
>--------------------------------</a><a name="qhmemT">-</a> |
68 |
|
69 |
qhmemT |
70 |
global memory structure for mem.c |
71 |
|
72 |
notes: |
73 |
users should ignore qhmem except for writing extensions |
74 |
qhmem is allocated in mem.c |
75 |
|
76 |
qhmem could be swapable like qh and qhstat, but then |
77 |
multiple qh's and qhmem's would need to keep in synch. |
78 |
A swapable qhmem would also waste memory buffers. As long |
79 |
as memory operations are atomic, there is no problem with |
80 |
multiple qh structures being active at the same time. |
81 |
If you need separate address spaces, you can swap the |
82 |
contents of qhmem. |
83 |
*/ |
84 |
typedef struct qhmemT qhmemT; |
85 |
extern qhmemT qhmem; |
86 |
|
87 |
struct qhmemT { /* global memory management variables */ |
88 |
int BUFsize; /* size of memory allocation buffer */ |
89 |
int BUFinit; /* initial size of memory allocation buffer */ |
90 |
int TABLEsize; /* actual number of sizes in free list table */ |
91 |
int NUMsizes; /* maximum number of sizes in free list table */ |
92 |
int LASTsize; /* last size in free list table */ |
93 |
int ALIGNmask; /* worst-case alignment, must be 2^n-1 */ |
94 |
void **freelists; /* free list table, linked by offset 0 */ |
95 |
int *sizetable; /* size of each freelist */ |
96 |
int *indextable; /* size->index table */ |
97 |
void *curbuffer; /* current buffer, linked by offset 0 */ |
98 |
void *freemem; /* free memory in curbuffer */ |
99 |
int freesize; /* size of free memory in bytes */ |
100 |
void *tempstack; /* stack of temporary memory, managed by users */ |
101 |
FILE *ferr; /* file for reporting errors */ |
102 |
int IStracing; /* =5 if tracing memory allocations */ |
103 |
int cntquick; /* count of quick allocations */ |
104 |
/* remove statistics doesn't effect speed */ |
105 |
int cntshort; /* count of short allocations */ |
106 |
int cntlong; /* count of long allocations */ |
107 |
int curlong; /* current count of inuse, long allocations */ |
108 |
int freeshort; /* count of short memfrees */ |
109 |
int freelong; /* count of long memfrees */ |
110 |
int totshort; /* total size of short allocations */ |
111 |
int totlong; /* total size of long allocations */ |
112 |
int maxlong; /* maximum totlong */ |
113 |
int cntlarger; /* count of setlarger's */ |
114 |
int totlarger; /* total copied by setlarger */ |
115 |
}; |
116 |
|
117 |
|
118 |
/*==================== -macros ====================*/ |
119 |
|
120 |
/*-<a href="qh-mem.htm#TOC" |
121 |
>--------------------------------</a><a name="memalloc_">-</a> |
122 |
|
123 |
qh_memalloc_(size, object, type) |
124 |
returns object of size bytes |
125 |
assumes size<=qhmem.LASTsize and void **freelistp is a temp |
126 |
*/ |
127 |
|
128 |
#ifdef qh_NOmem |
129 |
#define qh_memalloc_(size, freelistp, object, type) {\ |
130 |
object= (type*)qh_memalloc (size); } |
131 |
#else /* !qh_NOmem */ |
132 |
|
133 |
#define qh_memalloc_(size, freelistp, object, type) {\ |
134 |
freelistp= qhmem.freelists + qhmem.indextable[size];\ |
135 |
if ((object= (type*)*freelistp)) {\ |
136 |
qhmem.cntquick++; \ |
137 |
*freelistp= *((void **)*freelistp);\ |
138 |
}else object= (type*)qh_memalloc (size);} |
139 |
#endif |
140 |
|
141 |
/*-<a href="qh-mem.htm#TOC" |
142 |
>--------------------------------</a><a name="memfree_">-</a> |
143 |
|
144 |
qh_memfree_(object, size) |
145 |
free up an object |
146 |
|
147 |
notes: |
148 |
object may be NULL |
149 |
assumes size<=qhmem.LASTsize and void **freelistp is a temp |
150 |
*/ |
151 |
#ifdef qh_NOmem |
152 |
#define qh_memfree_(object, size, freelistp) {\ |
153 |
qh_memfree (object, size); } |
154 |
#else /* !qh_NOmem */ |
155 |
|
156 |
#define qh_memfree_(object, size, freelistp) {\ |
157 |
if (object) { \ |
158 |
qhmem .freeshort++;\ |
159 |
freelistp= qhmem.freelists + qhmem.indextable[size];\ |
160 |
*((void **)object)= *freelistp;\ |
161 |
*freelistp= object;}} |
162 |
#endif |
163 |
|
164 |
/*=============== prototypes in alphabetical order ============*/ |
165 |
|
166 |
void *qh_memalloc(int insize); |
167 |
void qh_memfree (void *object, int size); |
168 |
void qh_memfreeshort (int *curlong, int *totlong); |
169 |
void qh_meminit (FILE *ferr); |
170 |
void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, |
171 |
int bufsize, int bufinit); |
172 |
void qh_memsetup (void); |
173 |
void qh_memsize(int size); |
174 |
void qh_memstatistics (FILE *fp); |
175 |
|
176 |
#endif /* qhDEFmem */ |