Files
mercury/runtime/mercury_array_macros.h
Fergus Henderson 88a513b580 Reorganize the routines for allocating and deallocating memory:
Estimated hours taken: 8

Reorganize the routines for allocating and deallocating memory:

runtime/mercury_std.h:
runtime/mercury_misc.c:
runtime/mercury_memory.h:
runtime/mercury_memory.c:
	- Put the routines in the proper place.
		Previously the declarations and definitions of the memory
		allocation/deallocation routines were spread amoungst
		all four of these files; I moved the ones in mercury_std.h
		and mercury_misc.c so that they are now all defined
		in mercury_memory.{h,c}
	- Avoid unnecessary duplication
		The following routines did exactly the same thing,
		modulo bugs(!):
			allocate_bytes()	and newmem()
			deallocate_bytes()	and oldmem()
			make()			and allocate_object()
			make_many()		and allocate_array()
	- Use appropriate names.
		I added `MR_' prefixes, and ensured that macros that are not
		function-like macros use all uppercase.  I also used a more
		consistent naming scheme.
		Previously the names used were
			(1) checked_malloc, checked_realloc
			(2a) allocate_bytes, deallocate_bytes, reallocate_bytes,
				allocate_object, allocate_array, resize_array
			(2b) newmem, oldmem, resizemem,
				make, make_many, resize_many
		The new names are
			(1) MR_malloc, MR_free, MR_realloc,
				MR_NEW, MR_NEW_ARRAY, MR_RESIZE_ARRAY
			(2) MR_GC_malloc, MR_GC_free, MR_GC_realloc,
				MR_GC_NEW, MR_GC_NEW_ARRAY, MR_GC_RESIZE_ARRAY

runtime/*.[ch]:
trace/*.[ch]:
library/array.m:
library/benchmarking.m:
library/io.m:
library/std_util.m:
extras/odbc/odbc.m:
extras/aditi/aditi.m:
	Use the new names.
1999-10-18 15:47:39 +00:00

202 lines
6.7 KiB
C

/*
** Copyright (C) 1998-1999 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/
/*
** mercury_macros.h defines macros that are useful in more than one
** module of the Mercury runtime system.
*/
#ifndef MERCURY_ARRAY_MACROS_H
#define MERCURY_ARRAY_MACROS_H
#include "mercury_misc.h" /* for MR_memcpy */
/*
** This macro defines a safe way to perform assignment between
** array elements that are structures. The obvious way can cause
** gcc 2.7.2.3 to abort on x86 processors with the message
** "fixed or forbidden register was spilled."
*/
#ifdef MR_CANNOT_USE_STRUCTURE_ASSIGNMENT
#define MR_copy_array_element(array, to_index, from_index) \
do { \
MR_memcpy((void *) &array[to_index], \
(const void *) &array[from_index], \
sizeof(array[to_index])); \
} while(0)
#else
#define MR_copy_array_element(array, to_index, from_index) \
do { \
array[to_index] = array[from_index]; \
} while(0)
#endif /* ! MR_CANNOT_USE_STRUCTURE_ASSIGNMENT */
/*
** The MR_ensure_room_for_next macro works with a group of three variables
** that follow the pattern
**
** Item widgets = NULL;
** int widget_max = 0;
** int widget_next = 0;
**
** where widgets is a pointer to a MR_malloc'd array of items, widget_max
** gives the number of elements in the array, and widget_next is the
** index of the first free slot in the widgets array. Widget_max is
** zero if and only if widgets is NULL.
**
** MR_ensure_room_for_next(widget, Item, INIT_SIZE) checks whether
** there is enough room in the widgets array to add a new item.
** If not, doubles the size of the existing widgets array, or
** allocates an array of INIT_SIZE items if the widgets array
** has not been initialized before.
*/
#define MR_ensure_room_for_next(base, type, init) \
do { \
if (base##_next >= base##_max) { \
if (base##_max == 0) { \
base##_max = (init); \
base##s = MR_NEW_ARRAY(type, base##_max); \
} else { \
base##_max *= 2; \
base##s = MR_RESIZE_ARRAY(base##s, type, \
base##_max); \
} \
} \
} while(0)
/*
** MR_ensure_big_enough makes the same assumptions as MR_ensure_room_for_next,
** and operates almost the same way. The exception is that it does not assume
** that the array grows one item at a time; instead it ensures that the array
** is big enough to contain the element at index `slot'. Since with this regime
** there is no notion of the "next" slot, this macro does not access, nor does
** it require the existence of, base##_next.
*/
#define MR_ensure_big_enough(slot, base, type, init) \
do { \
if ((slot) >= base##_max) { \
if (base##_max == 0) { \
base##_max = max((init), (slot) + 1); \
base##s = MR_NEW_ARRAY(type, base##_max); \
} else { \
base##_max = max(base##_max * 2, (slot) + 1); \
base##s = MR_RESIZE_ARRAY(base##s, type, \
base##_max); \
} \
} \
} while(0)
/*
** MR_ensure_big_enough2 works like MR_ensure_big_enough, except that
** it resizes two arrays at once. These two arrays are named base##s1 and
** base##s2, and since they are always the same size, they share the
** base##_max variable.
*/
#define MR_ensure_big_enough2(slot, base, s1, s2, type, init) \
do { \
if ((slot) >= base##_max) { \
if (base##_max == 0) { \
base##_max = max((init), (slot) + 1); \
base##s1 = MR_NEW_ARRAY(type, base##_max); \
base##s2 = MR_NEW_ARRAY(type, base##_max); \
} else { \
base##_max = max(base##_max * 2, (slot) + 1); \
base##s1 = MR_RESIZE_ARRAY(base##s1, type, \
base##_max); \
base##s2 = MR_RESIZE_ARRAY(base##s2, type, \
base##_max); \
} \
} \
} while(0)
/*
** MR_bsearch(int next, int& element, bool& found, COMPARE)
**
** Given a sorted array, this macro performs a binary search.
** If the search is successful, MR_bsearch sets the `found' parameter
** to TRUE and the `element' parameter to the index of the desired item.
** If the search is unsuccessful, MR_bsearch sets `found' to FALSE;
** `element' will be clobbered.
**
** The number of the elements in the array is given by the `next' parameter.
** The `COMPARE' parameter should be an expression of type int which compares
** the value at the index specified by the current value of `element'
** with the desired value, and returns <0, 0, or >0 according to whether
** it is less than, equal to, or greater than the desired value.
**
** The name of the array to be searched is not explicitly a parameter;
** its identity is encoded in the boolean expression of the `COMPARE'
** parameter.
*/
#define MR_bsearch(next, element, found, COMPARE) \
do { \
int lo; \
int hi; \
int diff; \
\
/* \
** We initialize `element' here only to avoid gcc \
** warnings about possibly accessing an uninitialized \
** variable in code using MR_bsearch(). \
*/ \
(element) = 0; \
lo = 0; \
hi = (next) - 1; \
(found) = FALSE; \
while (lo <= hi) { \
(element) = (lo + hi) / 2; \
diff = (COMPARE); \
if (diff == 0) { \
(found) = TRUE; \
break; \
} else if (diff < 0) { \
lo = (element) + 1; \
} else { \
hi = (element) - 1; \
} \
} \
} while(0)
/*
** MR_prepare_insert_into_sorted(array[], int& next, int& element, COMPARE)
**
** Given a sorted array `items', this prepares for the insertion of a new
** item into the array at the proper point. It find the index at which
** the new item should be inserted, and moves all items at and above that
** index one position to the right to make room for the new item.
**
** The `next' parameter holds the number of elements in the array;
** it is incremented by this macro. The macro returns the index of the slot
** at which the new item should be inserted in the `element' parameter.
** The `COMPARE' parameter should be an expression of type int which compares
** the item at the index specified by the current value of `element' with
** the item being inserted, and returns <0, 0, or >0 according to whether
** it is less than, equal to, or greater than the item being inserted.
*/
#define MR_prepare_insert_into_sorted(items, next, element, COMPARE) \
do { \
(element) = (next) - 1; \
while ((element) >= 0 && (COMPARE) > 0) { \
MR_copy_array_element(items, element + 1, \
element); \
(element) -= 1; \
} \
(element) += 1; \
(next) += 1; \
} while(0)
#endif /* MERCURY_ARRAY_MACROS_H */