/[ascend]/trunk/ascend/utilities/mem.h
ViewVC logotype

Contents of /trunk/ascend/utilities/mem.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2039 - (show annotations) (download) (as text)
Wed May 20 01:34:20 2009 UTC (13 years, 6 months ago) by jpye
File MIME type: text/x-chdr
File size: 21557 byte(s)
Updated formatting/file headers for set.h, mem.h.
Added #includes to top of set.h, mem.h to ensure ascConfig is not missed.
Changed default IPOPT linear solver to MUMPS.
Added simple C++ test file for CONOPT.
1 /* ASCEND modelling environment
2 Copyright (C) 1997, 2009 Carnegie Mellon University
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18 *//** @file
19 Memory module.
20
21 It is convenient for pointers and ints to be the same
22 size, and most C compilers support this. However for
23 many machines (particularly ones with 16-bit words),
24 there is more RAM available than can be accessed by a
25 single int, so standard C pointers may only be able to
26 point to a limited region of memory. The matter is
27 further complicated by the fact that the pointer to
28 address conversion rules may be different for pointers
29 to functions (code) than for pointers to other objects
30 (data). This module attempts to partially circumvent
31 these obstacles, by allowing the user to address memory
32 with long ints.
33
34 As you can see, the above was written in the bad old
35 days pre-ANSI/STDC.
36 This file now serves to isolate bzero, bcopy, etc
37 from solver code should they become nonstandard.
38
39 The generic element memory manager is yet another
40 implementation of a fixed byte size malloc system
41 that is more efficient than most standard mallocs. This
42 is possible because we make the fixed size assumption.
43 The idea is clearly not original.
44 For best results, you must understand your memory
45 usage pattern and tune the mem_create_store() parameters
46 accordingly. See mem_create_store() for more information.
47
48 Detailed Description of Memory Manager:
49
50 The following definitions provide a generic and reasonably efficient memory
51 allocation system for situations where many many objects of the same size
52 need to be "allocated and deallocated" rapidly and stored efficiently:
53 that is to say when normal malloc is too slow and expensive.
54 This scheme does not play reference count games. Instead any elements that
55 have been created and then used and subsequently "freed" go on a list
56 and are handed out again at the next opportunity. The list is run LIFO.
57 The list is associated with the pool_store_t.
58
59 There is one restriction on the elements: they will be a multiple of the
60 size of a pointer, even if you specify otherwise. If this is too large,
61 write your own allocator. Think about how your elements align. On many
62 architectures doubles should only be stored at addresses that are
63 multiples of 8 bytes.
64 There is the implicit restriction on a store that it must contain
65 no more than MAXINT elements. If this is too small, write your own
66 allocator.
67
68 Even More Details
69
70 If you specify an element size that is not a nice multiple of your machine
71 word length, you are *very* likely to get data alignment (bus) errors.
72 E.g., if your element is not a convenient multiple of
73 sizeof(double) in size, double data are likely to die.
74
75 The allocation scheme looks like so:
76 <pre>
77 [struct pool_store_header | ]
78 __________________|
79 |
80 V
81 pool _____________________________________________________
82 | b | b | b | b | b | b | b | b | b | b | b | b | b |
83 -----------------------------------------------------
84 </pre>
85
86 where each b is a pointer to an array of size 'width' of elements.
87
88 The size characteristics of this scheme are tunable at run time so that
89 it can be scaled well when the number of elements and likely amount
90 of expansion required are known.
91
92 @todo Do we need to maintain the seemingly duplicate memory utilities and
93 pooled allocators of utilites/ascMalloc.c and utilities/mem.c? These
94 look like they could be consolidated into a single module.
95
96 *//*
97 Memory module
98 by Karl Westerberg, Ben Allan
99 Created: 6/90
100 Last in CVS: $Revision: 1.5 $ $Date: 1997/07/18 12:04:22 $ $Author: mthomas $
101
102 Authors: Karl Westerberg
103 Benjamin Andrew Allan
104
105 Dates: 06/90 - original version
106 08/94 - cleanup with bzero, bcopy, and corrected casting.
107 BAA, JJZ
108 05/95 - add nearly generic element allocation routines.
109 BAA
110 */
111
112 #ifndef ASC_MEM_H
113 #define ASC_MEM_H
114
115 #include <stdio.h>
116 #include <ascend/utilities/ascConfig.h>
117
118 #define mem_address(ptr) ((long)(ptr))
119 #define mem_code_address(ptr) ((long)(ptr))
120
121 #define mem_move_cast(from,too,nbytes) \
122 mem_move((POINTER)(from),(POINTER)(too),(size_t)(nbytes))
123 /**<
124 Copies nbytes of data from memory location from to memory location too.
125 The memory regions can be overlapping.
126
127 @param from Pointer to memory to copy from.
128 @param too Pointer to memory to receive copy.
129 @param nbytes The number of bytes to copy (size_t).
130 @return No return value.
131 @see mem_move()
132 */
133
134 ASC_DLLSPEC void mem_move(POINTER from, POINTER too, size_t nbytes);
135 /**<
136 Implementation function for mem_move_cast(). Do not call this
137 function directly - use mem_move_cast() instead.
138 */
139
140 #define mem_copy_cast(from,too,nbytes) \
141 mem_move_disjoint((POINTER)(from),(POINTER)(too),(size_t)(nbytes))
142 /**<
143 Copies nbytes of data from memory location from to memory location too.
144 The memory regions can NOT be overlapping.
145
146 @param from Pointer to memory to copy from.
147 @param too Pointer to memory to receive copy.
148 @param nbytes The number of bytes to copy (size_t).
149 @return No return value.
150 @see mem_move_disjoint()
151 */
152
153 ASC_DLLSPEC void mem_move_disjoint(POINTER from, POINTER too, size_t nbytes);
154 /**<
155 Implementation function for mem_copy_cast(). Do not call this
156 function directly - use mem_copy_cast() instead.
157 */
158
159 #define mem_repl_byte_cast(too,byte,nbytes) \
160 mem_repl_byte((POINTER)(too),(unsigned)(byte),(size_t)(nbytes))
161 /**<
162 Replaces nbytes of data at memory location too with byte.
163
164 @param too Pointer to start of block to be modified.
165 @param byte The character to write (unsigned int).
166 @param nbytes The number of bytes to modify (size_t).
167 @return No return value.
168 @see mem_repl_byte()
169 */
170
171 ASC_DLLSPEC void mem_repl_byte(POINTER too, unsigned byte, size_t nbytes);
172 /**<
173 Implementation function for mem_repl_byte_cast(). Do not call this
174 function directly - use mem_repl_byte_cast() instead.
175 */
176
177 #define mem_zero_byte_cast(too,byte,nbytes) \
178 mem_zero_byte((POINTER)(too),(unsigned)(byte),(size_t)(nbytes))
179 /**<
180 Zeroes nbytes of data at memory location too.
181 byte is ignored - it is a placeholder for mem_repl_byte
182 substitutability.
183
184 @param too Pointer to start of block to be modified.
185 @param byte Ignored (unsigned).
186 @param nbytes The number of bytes to zero (size_t).
187 @return No return value.
188 @see mem_zero_byte()
189 */
190
191 ASC_DLLSPEC void mem_zero_byte(POINTER too, unsigned byte, size_t nbytes);
192 /**<
193 Implementation function for mem_zero_byte_cast(). Do not call this
194 function directly - use mem_zero_byte_cast() instead.
195 */
196
197 #define mem_repl_word_cast(too,word,nwords) \
198 mem_repl_word((POINTER)(too),(unsigned)(word),(size_t)(nwords))
199 /**<
200 Replaces nwords of data at memory location too with word.
201
202 @param too Pointer to start of block to be modified.
203 @param word The word to write (unsigned).
204 @param nbytes The number of bytes to modify (size_t).
205 @return No return value.
206 @see mem_repl_word()
207 */
208
209 ASC_DLLSPEC void mem_repl_word(POINTER too, unsigned word, size_t nwords);
210 /**<
211 Implementation function for mem_repl_word_cast(). Do not call this
212 function directly - use mem_repl_word_cast() instead.
213 */
214
215 /* the following are pretty much a monument to Karl. */
216 #if 0
217 extern int mem_get_byte(long from); /**< Returns the byte located at from. */
218 #endif
219 ASC_DLLSPEC unsigned char mem_get_byte(long from); /**< Returns the byte located at from. */
220 ASC_DLLSPEC int mem_get_int(long from); /**< Returns the int located at from. */
221 ASC_DLLSPEC long mem_get_long(long from); /**< Returns the long located at from. */
222 ASC_DLLSPEC double mem_get_float(long from); /**< Returns the float located at from. */
223 ASC_DLLSPEC double mem_get_double(long from); /**< Returns the double located at from. */
224 ASC_DLLSPEC void mem_set_byte(long from, int b); /**< Sets the byte located at from. */
225 ASC_DLLSPEC void mem_set_int(long from, int i); /**< Sets the int located at from. */
226 ASC_DLLSPEC void mem_set_long(long from, long l); /**< Sets the long located at from. */
227 ASC_DLLSPEC void mem_set_float(long from, double f); /**< Sets the float located at from. */
228 ASC_DLLSPEC void mem_set_double(long from, double d); /**< Sets the double located at from. */
229
230 #define mem_get_unsigned(from) ((unsigned)mem_get_int(from))
231 /**< Returns the unsigned located at from. */
232 #define mem_set_unsigned(from,u) mem_set_int(from,(int)u)
233 /**< Sets the unsigned located at from. */
234
235 /*---------------------------------------------------------------------------
236 The following definitions provide a generic and reasonably efficient memory
237 allocation system for situations where many many objects of the same size
238 need to be "allocated and deallocated" rapidly and stored efficiently:
239 that is to say when normal malloc is too slow and expensive.
240 This scheme does not play reference count games. Instead any elements that
241 have been created and then used and subsequently "freed" go on a list
242 and are handed out again at the next opportunity. The list is run LIFO.
243 The list is associated with the mem_store_t.
244
245 There is one restriction on the elements: they will be a multiple of the
246 size of a pointer, even if you specify otherwise. If this is too large,
247 write your own allocator.
248 There is the implicit restriction on a store that it must contain
249 no more than MAXINT elements. If this is too small, write your own allocator.
250
251 Note for the intelligent:
252 If you specify an element size that is not a nice multiple of your machine
253 word length, you are *very* likely to get data alignment (bus) errors.
254 E.g., if your element is not a convenient multiple of sizeof(double) in size,
255 double data are likely to die.
256
257 The allocation scheme looks like so:
258 [struct mem_store_header | ]
259 __________________|
260 |
261 V
262 pool _____________________________________________________
263 | b | b | b | b | b | b | b | b | b | b | b | b | b |
264 -----------------------------------------------------
265 where each b is a pointer to an array of size 'width' of elements.
266
267 The size characteristics of this scheme are tunable at run time so that
268 it can be scaled well when the number of elements and likely amount
269 of expansion required are known.
270 ---------------------------------------------------------------------------*/
271
272 typedef struct mem_store_header *mem_store_t;
273 /**<
274 The token for this memory system. Internal details of the
275 implementation are private. Do not dereference or free this
276 pointer.
277 */
278
279 /**
280 Memory statistics data structure.
281 This is the reporting structure for a pool_store_header query.
282 */
283 struct mem_statistics {
284 double m_eff; /**< bytes in use / bytes allocated */
285 double m_recycle; /**< avg reuses per element */
286 int elt_total; /**< current elements existing in store*/
287 int elt_taken; /**< fresh elements handed out */
288 int elt_inuse; /**< elements the user currently has */
289 int elt_onlist; /**< elements awaiting reuse */
290 int elt_size; /**< bytes/element, as mem sees it */
291 int str_len; /**< length of active pool. */
292 int str_wid; /**< elements/pointer in pool. */
293 };
294
295 ASC_DLLSPEC void mem_get_stats(struct mem_statistics *m_stats, mem_store_t ms);
296 /**<
297 Get statistics about a memory store.
298 Stuffs the user's interface structure, m_stats, with info
299 derived from ms given.
300 If mem_LIGHTENING (see below) is TRUE, no statistics
301 except elt_total, elt_taken, elt_onlist, and elt_size are
302 available.
303
304 @param m_stats Pointer to a mem_statistics struct to receive
305 the info. If m_stats is NULL, an error message
306 is printed and the function returns.
307 @param ms Pointer to the memory store to query.
308 */
309
310 ASC_DLLSPEC mem_store_t mem_create_store(int length, int width, size_t eltsize,
311 int deltalen, int deltapool);
312 /**<
313 Creates and returns a new memory store. The returned mem_store_t
314 contains all the necessary accounting information, but in particular
315 the eltsize is fixed at creation. All elements requested from ms
316 will be pointers to eltsize bytes of memory.
317 Returns NULL if a store of the requested length*width*eltsize
318 cannot be initially allocated.<br><br>
319
320 The user may request more than length*width elements from the store:
321 this will cause it to grow. It will grow (internally) in chunks of
322 deltalen*width elements. The pool vector above grows in chunks of
323 deltapool, the extra pointers in it being NULL until needed.<br><br>
324
325 @param length The initial number of width*eltsize blocks that the
326 new pool store will contain. If length < 1, an error
327 message is printed and NULL is returned.
328
329 @param width Number of elements in each block.
330 Width should (for some architectures) be such that
331 width*eltsize = 2^n - 32 for some n fairly large
332 (heuristic: n= 9..13). Widths that are too large may
333 be prone to causing excess page faults, though the
334 process cpu time reported by the clock() can be much
335 better for extremely large sizes. If width < 1, an
336 error message is printed and NULL is returned.<br><br>
337 Widths that are too small will result in an excessive
338 number of pool expansions, which may severely limit
339 performance on some VM systems. See deltapool below
340 about pool expansions.<br><br>
341 If you know something about the page size of your
342 architecture, fiddling with width may help you reduce
343 your page fault or cache miss count in some uses.
344
345 @param eltsize Element size maintained by the pool.
346 For maximum efficiency, eltsize should be an integer
347 multiple of sizeof(void *). If it is not, elts will be
348 padded so that this is the case. This is to avoid
349 pointer data misalignment. This restriction may or
350 may not help avoid alignment problems with items inside
351 the user's element structure.
352
353 @param deltalen Number of additional pointers in the pool that will be
354 allocated when more elements are needed than are
355 available internally. deltalen must be at least 1 or
356 creation of the new pool will fail.
357
358 @param deltapool Size change of the pool array when expanded. It should
359 be as large as you are willing to tolerate. The pool
360 array starts out completely filled (all pointers allocated).
361 When the pool needs more pointers it gets them in chunks of
362 at least deltapool. These additional pointers will not
363 automatically have elements allocated to them; rather,
364 they will be initialized to NULL and filled in only as the
365 chunks of deltalen*width elements are required.
366
367 @return A pointer to the newly created pool store, NULL if an error occurred.
368 */
369
370 ASC_DLLSPEC void *mem_get_element(mem_store_t ms);
371 /**<
372 Get a usable element from the pool.
373 Returns a void pointer to a blob of memory of the eltsize
374 set when ms was created. You must cast it appropriately.
375 The blob data is not initialized in any particular way.
376
377 @param ms The pool store from which to retrieve an element.
378 If ms is NULL, then an error message is printed
379 and NULL is returned.
380 @return A pointer to the usable element, or NULL iff ms is NULL or
381 store growth is required and the operating system is unable
382 to allocate the required memory.
383 */
384
385 extern void mem_get_element_list(mem_store_t ms, int len, void **ellist);
386 /**<
387 NOT IMPLEMENTED.
388
389 Takes the pointer array, ellist, of length len provided by the user
390 and fills it with pointers to elements from the store.
391 There is not necessarily any relation (memory map wise) between the
392 locations pointed to by successive entries in the ellist returned.
393 Ellist should point to an array with enough space for len pointers.
394 Returns NULL in ellist[0] iff store growth is required and the operating
395 system is unable to allocate the required memory.<br><br>
396
397 The user is reminded that if he knows how many elements he needs
398 ahead of time, he is probably better off mallocing the array himself.
399
400 @todo Implement utilities/mem.c:mem_get_element_list() of remove
401 it from pool.h.
402 */
403
404 #define mem_DEBUG FALSE
405 /**<
406 Flag controlling extra checking of the pool management routines.
407 Setting mem_DEBUG to TRUE causes the mem_store routines to do
408 some RATHER expensive checking. It should be set to FALSE.
409 */
410 #define mem_LIGHTENING FALSE
411 /**<
412 Flag controlling extent of internal sanity checking.
413 Setting mem_LIGHTENING to TRUE causes mem_store routines to assume
414 the user is perfect: i.e. no sanity checks are at all necessary and most
415 internal accounting can be disabled. No one with an ounce of sanity
416 would ever set this flag to TRUE unless the code using the
417 mem module was proven bug free. It makes the allocator smaller
418 and faster, though, by ~15%. <br><br>
419
420 This flag exists to make it easy to test the theory that the
421 accounting overhead in this code is not of significant cost.
422 Below 1e5 elements it really isn't bad enough to justify the
423 assumption that the user is perfect.
424 */
425
426 ASC_DLLSPEC void mem_free_element(mem_store_t ms, void *eltpointer);
427 /**<
428 Releases an element back to the store.
429 If you return the same pointer twice, we will have
430 no qualms about returning it to you twice. We won't necessarily
431 return it to you twice, though.<br><br>
432
433 If mem_DEBUG is TRUE, eltpointer will be checked for belonging
434 to ms. If you call mem_free_element() with a pointer the ms does
435 not recognize, it will not be freed and a message will be
436 sent to ASCERR.<br><br>
437
438 If mem_DEBUG is FALSE, eltpointer will be assumed to belong
439 with the ms in question. The implications of handing
440 mem_free_element() an element of the wrong size or from the
441 wrong ms (bearing in mind the LIFO reuse of elements) should be
442 obvious. If they are not, stop using these routines.<br><br>
443
444 If at any time the number of elements freed exceeds the number
445 handed out, we will whine (unless mem_LIGHTENING). If ms is
446 NULL, and error message is printed and the function returns.
447 If eltpointer is NULL, we will ignore it completely.
448
449 @param ms The memory store to modify.
450 @param eltpointer The element to return to the pool.
451 @return No return value.
452 */
453
454 ASC_DLLSPEC void mem_clear_store(mem_store_t ms);
455 /**<
456 Clears the books in ms. That is, we reset the ms to think
457 that __all__ elements are freshly available and have never
458 been handed out. If ms is NULL, an error message is printed
459 and the function returns.<br><br>
460
461 If mem_DEBUG is TRUE, it first verifies that all elements have
462 been mem_freed first and whines if not.
463 Get and free calls will be balanced to see if spurious elements
464 have been handed in. (This is a heuristic check).
465 The clear process will cause any spurious pointers that were
466 turned in via mem_free_element() to be forgotten about.<br><br>
467
468 Clearing a store is not necessary for mem_destroy_store().
469 Recycling is faster from the recycle list than from a cleared store, ~2%.
470 Clear is provided for users who want to obtain elements with a higher
471 probability of successive elements being near each other.
472
473 @param ms The memory store to clear.
474 @return No return value.
475 */
476
477 ASC_DLLSPEC void mem_destroy_store(mem_store_t ms);
478 /**<
479 Deallocates everything associated with the ms.
480 If mem_DEBUG is TRUE, it first verifies that all elements
481 have been mem_freed first and whines if not.
482 If pmem_DEBUG is FALSE, just nukes everything unconditionally.
483 If ms is NULL, an error message is printed and the function
484 returns.
485
486 @paramms The memory store to destroy.
487 */
488
489 extern void mem_print_store(FILE *fp, mem_store_t ms, unsigned detail);
490 /**<
491 Prints statistics about a mem_store_t to the file stream given.
492 Which stats get printed depends on detail.
493 - If detail 0, displays just summary statistics.
494 - If detail 1, just internal statistics.
495 - If detail >1, displays both.
496
497 @param fp The open file stream on which to print the report.
498 @param ms The memory store on which to report.
499 @param detail The level of detail to print:
500 0 = summary, 1 = internal stats, >1 = both.
501 */
502
503 extern size_t mem_sizeof_store(mem_store_t ms);
504 /**<
505 Retrieves the current total byte usage of the store.
506 Returns 0 if an invalid pool store is specified.
507
508 @param ms The memory store to query.
509 @return The total bytes currently used by the memory store.
510 */
511
512 #endif /* ASC_MEM_H */
513

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22