@@ -73,6 +73,88 @@ void pntrNCpy(pntrString *s, const pntrString *t, long n);
73
73
74
74
vstring g_qsortKey ; /* Used by qsortStringCmp; pointer only, do not deallocate */
75
75
76
+ /*!
77
+ * \page suballocation Suballocator
78
+ *
79
+ * Metamath does not free memory by returning it to the operating system again.
80
+ * To reduce frequent system de/allocation calls, it instead implements a
81
+ * suballocator. Each chunk of memory allocated from the system (we call them
82
+ * \ref block "block" in this documentation) is equipped with a hidden header
83
+ * containing administrative information private to the suballocator.
84
+ *
85
+ * During execution chunks of memory, either complete \ref block "blocks" or
86
+ * \ref fragmentation "fragments" thereof, become free again. The suballocator
87
+ * adds them then to internal **pools** for reuse, one dedicated to totally
88
+ * free blocks (\a memFreePool), the other to fragmented ones (\a memUsedPool).
89
+ * We call these pools **free block array** and **used block array** in this
90
+ * documentation. Fully occupied blocks are not tracked by the suballocator.
91
+ *
92
+ * Although the suballocator tries to avoid returning memory to the system, it
93
+ * can do so under extreme memory constraints, or when built-in limits are
94
+ * surpassed.
95
+ *
96
+ * The suballocator was designed with stack-like memory usage in mind, where
97
+ * data of the same type is pushed at, or popped off the end all the time.
98
+ * Each \ref block block supports this kind of usage out of the box (see
99
+ * \ref fragmentation).
100
+ */
101
+ /*!
102
+ * \page fragmentation Fragmented blocks
103
+ *
104
+ * Memory fragmentation is kept simple in Metamath. If a \ref block "block"
105
+ * contains both consumed and free space, all the free space is at the end.
106
+ * This scheme supports the idea of stack-like memory usage, where free space
107
+ * grows and shrinks behind a stack in a fixed size memory area, depending on
108
+ * its usage.
109
+ *
110
+ * Other types of fragmentation is not directly supported by the
111
+ * \ref suballocation "suballocator".
112
+ */
113
+
114
+ /*! \page block Block of memory
115
+ *
116
+ * Each block used by the \ref suballocation "suballocator" is formally treated
117
+ * as an array of pointer (void*). It is divided into an administrative
118
+ * header, followed by elements reserved for application data. The header is
119
+ * assigned elements -3 to -1 in the formal array, so that application data
120
+ * starts with element 0. A **pointer to the block** always refers to element
121
+ * 0, so the header appears somewhat hidden. Its **size** is given by the
122
+ * bytes reserved for application data, not including the administrative header.
123
+ *
124
+ * The header elements are formally void*, but reinterpreted as long integer.
125
+ * The values support a stack, where data is pushed at and popped off the end
126
+ * during the course of execution. The semantics of the header elements are:
127
+ *
128
+ * offset -1:\n
129
+ * is the current size of the stack (in bytes, not elements!),
130
+ * without header data. When interpreted as an offset into the stack, it
131
+ * references the first element past the top of the stack. (See
132
+ * \ref fragmentation "fragmentation")
133
+ *
134
+ * offset -2:\n
135
+ * the allocated size of the array, in bytes, not counting the
136
+ * header. When used as a stack, it marks the limit where the stack
137
+ * overflows.
138
+ *
139
+ * offset -3:\n
140
+ * If this block has free space at the end (is \ref fragmentation
141
+ * "fragmented"), then it contains its index in the used blocks array, see
142
+ * \a memUsedPool. A value of -1 indicates it is either fully occupied or
143
+ * totally free. In any of these cases it is not kept in the used blocks
144
+ * array.
145
+ */
146
+
147
+ /*! \page Pool
148
+ * A pool is an array of pointers pointing to \ref block "blocks". It may only
149
+ * be partially filled, so it is usually accompanied by two variables giving
150
+ * its current fill state and its capacity.
151
+ *
152
+ * In Metamath a pool has no gaps in between.
153
+ *
154
+ * The \ref suballocation "suballocator" uses two pools:
155
+ * - the **free block array** pointed to by \a memFreePool;
156
+ * - the **used block array** pointed to by \a memUsedPool.
157
+ */
76
158
77
159
/* Memory pools are used to reduce the number of malloc and alloc calls that
78
160
allocate arrays (strings or nmbr/pntrStrings typically). The "free" pool
@@ -95,26 +177,32 @@ vstring g_qsortKey; /* Used by qsortStringCmp; pointer only, do not deallocate *
95
177
#define MEM_POOL_GROW 1000 /* Amount that a pool grows when it overflows. */
96
178
/*??? Let user set this from menu. */
97
179
long poolAbsoluteMax = 1000000 ; /* Pools will be purged when this is reached */
180
+ /*!
181
+ * \var long poolTotalFree
182
+ * contains the number of free space available in bytes, in both pools
183
+ * \a memFreePool and \a memUsedPool, never counting the hidden headers at the
184
+ * beginning of each block, see \ref block.
185
+ */
98
186
long poolTotalFree = 0 ; /* Total amount of free space allocated in pool */
99
187
/*E*/ long i1 ,j1_ ,k1 ; /* 'j1' is a built-in function */
100
188
/*!
101
189
* \var void** memUsedPool
102
190
* \brief pointer to the pool of fragmented memory blocks
103
- * Memory fragmentation is kept simple in Metamath. If a block contains both
104
- * consumed and free space, all of the free space is at the end. Fragmented
105
- * blocks with free space are kept in the used block array, that memUsedPool
106
- * points to. For the notion of block, suballocator see \a memFreePool. This
107
- * scheme supports in particular stack like memory, where data is pushed at and
108
- * popped off the end.
191
+ *
192
+ * If a \ref block "block" contains both consumed and free space, it is
193
+ * \ref fragmentation "fragmented". All fragmented blocks are kept in the
194
+ * **used block array**, that memUsedPool points to. See \ref suballocation
195
+ * "suballocator". Since free space appears at the end of a \ref block
196
+ * "block", this scheme supports in particular stack like memory, where data is
197
+ * pushed at and popped off the end.
109
198
*
110
199
* The used blocks array does initially not exist. This is indicated by a
111
- * null value. Once this array is needed, space for it it is allocated from
112
- * the system.
200
+ * null value. Once this array is needed, space for it is allocated from the
201
+ * system.
113
202
*
114
203
* The used block array may only be partially occupied, in which case elements
115
204
* at the end of the array are unused. Its current usage is given by
116
- * \a memUsedPoolSize. Its current size including unused elements, is given by
117
- * \a memUsedPoolMax.
205
+ * \a memUsedPoolSize. Its capacity is given by \a memUsedPoolMax.
118
206
*
119
207
* \invariant Each block in the used blocks array has its index noted in its
120
208
* hidden header, for backward reference.
@@ -155,58 +243,19 @@ long memUsedPoolMax = 0; /* Maximum # of entries in 'in use' table (grows
155
243
* \var void** memFreePool
156
244
* \brief pointer to the pool of completely free memory blocks
157
245
*
158
- * **suballocator**
159
- *
160
- * Metamath does not free memory by returning it to the operating system again.
161
- * Instead it has a suballocator that marks them as unused. During execution
162
- * chunks of memory become unused, either completely, or through fragmentation.
163
- * The suballocator keeps track of these by entering them either into a free
164
- * block array, or into a used block array. The idea behind this suballocation
165
- * scheme is to reduce the number of system malloc and alloc calls.
166
- *
167
- * Although the suballocator tries to avoid returning memory to the system, it
168
- * can do so under extreme memory constraints.
169
- *
170
- * The suballocator is initially neither equipped with a free block array,
171
- * pointed to by memFreePool, or a used block array, see \a memUsedPool. Both
172
- * are null then, but once memory is returned to the suballocator again, it
173
- * allocates some space for the needed array.
246
+ * The \ref suballocation "suballocator" is initially not equipped with a
247
+ * **free block array**, pointed to by memFreePool, indicated by a null value.
248
+ *
249
+ * Once a \ref \block "memory block" is returned to the \ref suballocation
250
+ * again, it allocates some space for the now needed array.
174
251
*
175
- * The free block array contains totally unused blocks. The array may only
176
- * partially be occupied, in which case The elements at the end are the unused
177
- * ones. Its current fill size is given by \a memFreePoolSize. Its capacity
178
- * is given by \a memFreePoolMax.
252
+ * The ** free block array** contains only totally free \ref block "blocks".
253
+ * This array may only be partially occupied, in which case the elements at the
254
+ * end are the unused ones. Its current fill size is given by
255
+ * \a memFreePoolSize. Its capacity is given by \a memFreePoolMax.
179
256
*
180
257
* Fragmented blocks are kept in a separate \a memUsedPool. The suballocator
181
258
* never tracks fully used blocks.
182
- *
183
- * **block of memory**
184
- *
185
- * Each block used by the suballocater is formally treated as an array of
186
- * pointer (void*). It is divided into an administrative header, followed by
187
- * elements reserved for application data. The header is assigned elements -3
188
- * to -1 in the formal array, so that application data starts with element 0.
189
- * A pointer to the block always refers to element 0, so the header appears
190
- * somewhat hidden.
191
- *
192
- * The header elements are reinterpreted as long integer. The values support
193
- * a stack, where data is pushed at and popped off the end during the course of
194
- * execution. The semantics of the header elements are:
195
- *
196
- * offset -1:\n
197
- * is the current size of the stack (in bytes, not elements!),
198
- * without header data. When interpreted as an offset into the stack, it
199
- * references the first element past the top of the stack.
200
- *
201
- * offset -2:\n
202
- * the allocated size of the array, in bytes, not counting the
203
- * header. When used as a stack, it marks the limit where the stack
204
- * overflows.
205
- *
206
- * offset -3:\n
207
- * If this block has free space at the end (is fragmented), then it contains
208
- * its index in the used blocks array, see \a memUsedPool. A value of -1
209
- * indicates it has no free space left, hence is not held in this pool.
210
259
*/
211
260
void * * memFreePool = NULL ;
212
261
/*!
@@ -227,8 +276,8 @@ long memFreePoolSize = 0; /* Current # of available, allocated arrays */
227
276
* \attention this is the number of individual free blocks, not the accumulated
228
277
* bytes contained.
229
278
*
230
- * The Metamath suballocator holds free blocks in a free block array. It may
231
- * only partially be occupied. Its total capacity is kept in this variable. For
279
+ * The Metamath suballocator holds free blocks in a ** free block array** . It
280
+ * may only be partially occupied. Its total capacity is kept in this variable. For
232
281
* further information see \a memFreePool.
233
282
*
234
283
* This variable may grow during a reallocation process.
@@ -2579,6 +2628,35 @@ void pntrZapLen(pntrString *s, long length) {
2579
2628
2580
2629
/* Copy a string to another (pre-allocated) string */
2581
2630
/* Dangerous for general purpose use */
2631
+ /*!
2632
+ * \brief copies a null pointer terminated \a pntrString to a destination
2633
+ * \a pntrString.
2634
+ *
2635
+ * This function determines the length of the source \p t by scanning for a
2636
+ * terminating null pointer element. The destination \p s must have enough
2637
+ * space for receiving this amount of pointers, including the terminal null
2638
+ * pointer. Then the source pointers are copied beginning with that at the
2639
+ * lowest address to the destination area \p t, including the terminal null
2640
+ * pointer.
2641
+ *
2642
+ * \attention make sure the destination area pointed to by \p s has enough
2643
+ * space for the copied pointers.
2644
+ *
2645
+ * \param [out] s (not null) pointer to the target array receiving the copied
2646
+ * pointers. This need not necessarily be the first element of the array.
2647
+ * \param [in] t (not null) pointer to the start of the source array terminated
2648
+ * by a null pointer.
2649
+ *
2650
+ * \pre
2651
+ * - \p t is terminated by the first null pointer element.
2652
+ * - the target array \p s must have enough free space to hold the source array
2653
+ * \p t including the terminal null pointer.
2654
+ * - \p s and \p t can overlap if \p t points to a later element than \a s
2655
+ * (move left semantics)
2656
+ * \invariant
2657
+ * If \p s is contained in a \ref block "block", its administrative header is
2658
+ * NOT updated.
2659
+ */
2582
2660
void pntrCpy (pntrString * s , const pntrString * t ) {
2583
2661
long i ;
2584
2662
i = 0 ;
0 commit comments