Initial revision
[ssr] / StraySrc / Libraries / Steel / h / flex
1 /*
2 * flex.h
3 *
4 * A shifting heap for RISC OS applications [APCS edition]
5 *
6 * © 1996-1998 Straylight
7 */
8
9 /*----- Licensing note ----------------------------------------------------*
10 *
11 * This file is part of Straylight's Steel library.
12 *
13 * Steel is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * Steel is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with Steel. If not, write to the Free Software Foundation,
25 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 /*----- Foreword: what are all those funny symbols in the comments? -------*
29 *
30 * This file has been marked up so that `lgrind' can process it to produce
31 * a pretty typeset listing. Text enclosed by at signs is typeset like
32 * normal code. There are some other neat things, but you get the idea.
33 * Note that you'll need a hacked version of lgrind.sty to get the rows
34 * of dashes typeset properly: they'll just look odd otherwise.
35 *
36 * Quite a lot of work has been put into this header file recently to make
37 * the descriptions of the routines clear and complete. As a result, they
38 * probably read like excerpts from ISO 9899 (Computer Languages -- C).
39 */
40
41 /* --- Standard-ish preamble --- *
42 *
43 * If I understand the compiler properly, then use special magic to prevent
44 * wasted cycles reading this file more than once. The normal #ifndef
45 * stuff should keep GNU C happy because it's particularly intelligent like
46 * that; Norcroft C would rather have some magic pragmae specified. The
47 * usual protection is added to stop compilers of the brain-damaged version
48 * of C invented by Bjarne Stroutrup generating duff linker symbols.
49 */
50
51 #ifdef __CC_NORCROFT
52 #pragma force_top_level
53 #pragma include_only_once
54 #endif
55
56 #ifndef __flex_h
57 #define __flex_h
58
59 #ifdef __cplusplus
60 extern "C" {
61 #endif
62
63 /*----- How it all works --------------------------------------------------*
64 *
65 * In order to allow the blocks to move around, you need to tell flex where
66 * your pointer to each block is. You do this with an anchor pointer (i.e.
67 * it points at your anchor for the block). Flex is quite at liberty to
68 * change your anchors at any time it wants to, so if you don't want your
69 * blocks to move, don't call flex. You must ensure that you always access
70 * data in flex blocks through the anchor, unless you're really sure the
71 * block won't move.
72 *
73 * Unlike older (Acorn) versions, Straylight flex doesn't ensure that the
74 * heap is always as compact as possible. Instead, calling @flex_reduce@
75 * will attempt to compact the heap a little bit, so if you call it a lot,
76 * the heap will eventually become very compact. It is envisaged that you
77 * call @flex_reduce@ every Wimp_Poll. STEEL's @wimpt_poll@ does this for
78 * you.
79 *
80 * There is another call, @flex_compact@, which will compact the heap fully.
81 * This isn't terribly useful most of the time, since flex compacts itself
82 * if it runs out of memory.
83 *
84 * @flex_budge@ is not currently supported. If there is a demand for it,
85 * it may be added in later, but probably not, because in the author's
86 * opinion it's just a request for unpredictable crashes.
87 */
88
89 /* --- A flex anchor pointer --- *
90 *
91 * Due to Acorn brain-damage, this is a void ** instead of a void *, meaning
92 * that you end up with typecasts all over the shop. Strictly speaking,
93 * such typecasts invoke undefined behaviour, although it works under all
94 * known ARM compilers, and if nyone tries to use this code on any other
95 * platform they get what they deserve, because the code's written in
96 * assembler ;-).
97 */
98
99 typedef void **flex_ptr;
100
101 /* --- @flex_init@ --- *
102 *
103 * Arguments: ---
104 *
105 * Returns: ---
106 *
107 * Use: Initialises flex. It doesn't bother to check that any
108 * memory is available.
109 *
110 * This is now just a macro which calls the @flex_dinit@
111 * routine with a null pointer argument, forcing the heap to
112 * be created in the task;s WimpSlot.
113 */
114
115 #define flex_init(x) flex_dinit(0, 0);
116
117 /* --- @flex_dinit@ --- *
118 *
119 * Arguments: @const char *name@ = name of dynamic area to create, or null
120 * @long max@ = maximum size of the area
121 *
122 * Returns: ---
123 *
124 * Use: Initialises flex and creates a (zero-sized) initial heap.
125 * If the @name@ argument is not a null pointer, and the
126 * current operating system is RISC OS 3.50 or later, then an
127 * attempt is made to create the heap in a dynamic area. If
128 * this fails, or the attempt wasn't made, then the heap is
129 * created in the task's wimpslot instead.
130 *
131 * The author strongly urges you not to use the dynamic area
132 * option without good reason. Dynamic areas are limited to
133 * 16MB, to avoid problems with address space fragmentation
134 * on machines with large quantities of real memory.
135 *
136 * It is your responsibility to remove the dynamic area when
137 * your program quits. Usually you will do this by calling
138 * @atexit(flex_die)@ just after initialisation of the heap,
139 * although some other method may be necessary if you're not
140 * using the complete C library for some reason.
141 */
142
143 extern void flex_dinit(const char */* name */, long /* max */);
144
145 /* --- @flex_die@ --- *
146 *
147 * Arguments: ---
148 *
149 * Returns: ---
150 *
151 * Use: Tidies up anything as required when the program end. It is
152 * recommended that this be done via the C library's @atexit@
153 * mechanism or some equivalent for freestanding applications.
154 * This is only necessary when flex has created a dynamic area
155 * for this application, although provided flex has initialised
156 * it is never wrong to register this routine as a closedown
157 * function.
158 */
159
160 extern void flex_die(void);
161
162 /* --- @flex_alloc@ --- *
163 *
164 * Arguments: @flex_ptr anchor@ = address of the anchor for this block
165 * @unsigned long size@ = size of the block required
166 *
167 * Returns: Nonzero if the block was successfuly allocated, zero if
168 * there wasn't enough memory.
169 *
170 * Use: Allocates a shifting heap block. The address is stored in
171 * the pointer variable whose address was passed in @anchor@.
172 * This pointer will be updated automatically when the block is
173 * moved during compaction. The size of the allocated block
174 * will be at least @size@ bytes.
175 *
176 * If there is not enough memory currently available in the
177 * heap, flex may attempt to reclaim space by compacting the
178 * heap. As a result, other heap blocks may be moved; this was
179 * not possible under the Acorn implementation. The new block
180 * will always be placed at the end of the heap.
181 *
182 * During compaction, blocks only move to lower addresses.
183 * When a block is grown, blocks above it move to higher
184 * addresses. As a consequence of this, a block at the base
185 * of the heap will never be moved by flex. This fact may be
186 * useful, for example if you want to create a resizing non-
187 * shifting heap.
188 */
189
190 extern int flex_alloc(flex_ptr /* anchor*/, unsigned long /* size */);
191
192 /* --- @flex_free@ --- *
193 *
194 * Arguments; @flex_ptr@ anchor = address of the anchor for this block
195 *
196 * Returns: ---
197 *
198 * Use: Frees the memory occupied by the block whose anchor address
199 * is given in @anchor@. The memory is marked as unoccupied
200 * and reclaimed during compaction later. Therefore freeing
201 * blocks is an extremely cheap operation, as it should be.
202 */
203
204 extern void flex_free(flex_ptr /* anchor */);
205
206 /* --- @flex_extend@ --- *
207 *
208 * Arguments: @flex_ptr anchor@ = address of the anchor for the block
209 * @unsigned long size@ = new size for the block
210 *
211 * Returns: Nonzero if the resize was successful, or zero if there
212 * wasn't enough memory.
213 *
214 * Use: Changes the size of the block whose anchor address is given
215 * by @anchor@; the new size will be at least @size@ bytes.
216 *
217 * If @size@ is less than or equal to the current size of the
218 * block, this operation cannot fail; any space at the end of
219 * the block which is no longer required is marked as unused
220 * and reclaimed later during compaction. No blocks are moved.
221 *
222 * If @size@ is greater than the current size of the block,
223 * this operation might fail. Also, flex might compact the
224 * heap in an attempt to obtain enough free memory, so all
225 * blocks might move. Blocks above the one being grown will
226 * move anyway; blocks below the one being resized did not
227 * move in this way under the Acorn implementation.
228 */
229
230 extern int flex_extend(flex_ptr /* anchor */, unsigned long /* newsize */);
231
232 /* --- @flex_midextend@ --- *
233 *
234 * Arguments: @flex_ptr anchor@ = address of the anchor for the block
235 * @unsigned long at@ = index at which to insert or remove bytes
236 * @long by@ = number of bytes to insert or remove
237 *
238 * Returns: Nonzero if the resize was successful, or zero if there
239 * wasn't enough memory.
240 *
241 * Use: Changes the size of the block whose anchor address is given
242 * by @anchor@. Bytes are inserted or removed at the given
243 * offset @at@, which must be between 0 and @flex_size(anchor)@
244 * inclusive. If @by@ is positive, then @by@ bytes are
245 * inserted before the indexed byte; if it is negative, then
246 * @-by@ bytes are deleted from just before @at@. Always,
247 * the data which was at offset @at@ is now at offset @at + by@.
248 * The value of @by@ must be at least @-flex_size(anchor)@.
249 *
250 * If @by@ is negative, this operation cannot fail; the bytes
251 * are deleted by calling @memmove@, and any space at the end of
252 * the block which is no longer required is marked as unused
253 * and reclaimed later during compaction. No blocks are moved.
254 *
255 * If @by@ is positive, this operation might fail. Also, flex
256 * might compact the heap in an attempt to obtain enough free
257 * memory, so all blocks might move. Blocks above the one
258 * being extended will move anyway; blocks below the one being
259 * resized did not move in this way under the Acorn
260 * implementation. If the block was resized successfully, bytes
261 * with undefined values are inserted at the correct place by
262 * calling @memmove@. This does not occur if the operation
263 * failed.
264 */
265
266 extern int flex_midextend(flex_ptr /* anchor */,
267 unsigned long /* at */ , long /* by */);
268
269 /* --- @flex_size@ --- *
270 *
271 * Arguments: @flex_ptr anchor@ = address of the anchor for the block
272 *
273 * Returns: The size of the block. This is returned as a @signed int@
274 * for historical reasons: old versions of flex returned this
275 * value, and it's likely that old code will generate large
276 * numbers of annoying and useless `implicit narrowing cast'
277 * if I change the return type to @unsigned long@. However,
278 * if you read the value as an @unsigned long@ you won't get
279 * get any warnings, and you'll also get the correct value.
280 *
281 * Use: Returns the current size of the block in bytes. This is
282 * the `conceptual' size: the actual amount of memory occupied
283 * by the block depends on unspecified bookkeeping overhead and
284 * alignment applied to this value. The size returned is the
285 * @size@ argument passed to the most recent @flex_alloc@ or
286 * @flex_extend@ call referring to this block, added to the
287 * sum of all the @by@ arguments passed to @flex_midextend@
288 * since then.
289 */
290
291 extern int flex_size(flex_ptr /* anchor */);
292
293 /* --- @flex_reduce@ --- *
294 *
295 * Arguments: ---
296 *
297 * Returns: ---
298 *
299 * Use: Performs a small part of the compaction process. Calling
300 * @flex_reduce@ enough times will result in the heap becoming
301 * compacted; further calls will have no effect.
302 *
303 * The idea is that you call @flex_reduce@ periodically, e.g.,
304 * when you receive a null event code.
305 */
306
307 extern void flex_reduce(void);
308
309 /* --- @flex_compact@ --- *
310 *
311 * Arguments: ---
312 *
313 * Returns: ---
314 *
315 * Use: Fully compacts the heap. This might be useful if you've
316 * just done a lot of freeing and compaction by normal
317 * processes takes too long.
318 */
319
320 extern void flex_compact(void);
321
322 /* --- kernel slot extension functions --- *
323 *
324 * Only @flex_dont_budge@ is supported at the moment. Note that the
325 * interfaces as defined here are broken, because the size should really
326 * be an unsigned type. However, since both routines simply do @return (0)@
327 * this isn't too much of a problem.
328 */
329
330 extern int flex_dont_budge(int /* n */, void **/* p */);
331 extern int flex_budge(int /* n */, void **/* p */);
332
333 #ifdef __cplusplus
334 }
335 #endif
336
337 /*----- That's all, folks -------------------------------------------------*/
338
339 #endif